Skip to content

cxx-qt-gen: remove hidden module #618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 75 additions & 42 deletions crates/cxx-qt-gen/src/generator/rust/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use std::collections::BTreeMap;

use crate::{
generator::{
naming::{namespace::NamespaceName, qobject::QObjectName, CombinedIdent},
rust::qobject::GeneratedRustQObjectBlocks,
utils::rust::syn_type_is_cxx_bridge_unsafe,
rust::qobject::GeneratedRustQObject,
utils::rust::{
syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified,
syn_type_is_cxx_bridge_unsafe,
},
},
parser::constructor::Constructor,
};

use convert_case::{Case, Casing};
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{parse_quote, parse_quote_spanned, spanned::Spanned, Expr, Ident, Item, Result, Type};
use syn::{
parse_quote, parse_quote_spanned, spanned::Spanned, Expr, FnArg, Ident, Item, Path, Result,
Type,
};

const CONSTRUCTOR_ARGUMENTS: &str = "CxxQtConstructorArguments";
const BASE_ARGUMENTS: &str = "CxxQtConstructorBaseArguments";
Expand Down Expand Up @@ -57,7 +65,7 @@ fn argument_members(args: &[Type]) -> Vec<TokenStream> {
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!(
Expand All @@ -66,7 +74,7 @@ fn generate_default_constructor(
);
let namespace_internals = &namespace.internal;

GeneratedRustQObjectBlocks {
GeneratedRustQObject {
cxx_mod_contents: vec![parse_quote! {
extern "Rust" {
#[cxx_name = "createRs"]
Expand Down Expand Up @@ -136,16 +144,20 @@ pub fn generate(
constructors: &[Constructor],
qobject_idents: &QObjectName,
namespace: &NamespaceName,
) -> Result<GeneratedRustQObjectBlocks> {
qualified_mappings: &BTreeMap<Ident, Path>,
module_ident: &Ident,
) -> Result<GeneratedRustQObject> {
if constructors.is_empty() {
return Ok(generate_default_constructor(qobject_idents, namespace));
}

let mut result = GeneratedRustQObjectBlocks::default();
let mut result = GeneratedRustQObject::default();
let namespace_internals = &namespace.internal;

let qobject_name = &qobject_idents.cpp_class.cpp;
let qobject_name_rust = &qobject_idents.cpp_class.rust;
let qobject_name_rust_qualified =
syn_ident_cxx_bridge_to_qualified_impl(qobject_name_rust, qualified_mappings);
let qobject_name_snake = qobject_name.to_string().to_case(Case::Snake);

let rust_struct_name_rust = &qobject_idents.rust_struct.rust;
Expand All @@ -171,15 +183,30 @@ pub fn generate(
let route_arguments_rust = format_ident!("route_arguments_{qobject_name_snake}_{index}");
let route_arguemnts_cxx = format!("routeArguments{index}");

let argument_types = &constructor.arguments;
let argument_types_qualified: Vec<Type> = constructor
.arguments
.iter()
.map(|arg| syn_type_cxx_bridge_to_qualified(arg, qualified_mappings))
.collect();

let route_arguments_parameters: Vec<TokenStream> = constructor
let route_arguments_parameters: Vec<FnArg> = 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<FnArg> = 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
Expand Down Expand Up @@ -273,40 +300,40 @@ pub fn generate(
result.cxx_qt_mod_contents.append(&mut vec![parse_quote_spanned! {
constructor.imp.span() =>
#[doc(hidden)]
pub fn #route_arguments_rust(#(#route_arguments_parameters),*) -> #arguments_rust {
pub fn #route_arguments_rust(#(#route_arguments_parameter_qualified),*) -> #module_ident::#arguments_rust {
// These variables won't be used if the corresponding argument list is empty.
#[allow(unused_variables)]
#[allow(clippy::let_unit_value)]
let (
new_arguments,
base_arguments,
initialize_arguments
) = <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>
) = <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>
::route_arguments((#(#assign_arguments,)*));
#arguments_rust {
base: #init_base_arguments,
initialize: #init_initalize_arguments,
new: #init_new_arguments,
#module_ident::#arguments_rust {
base: #module_ident::#init_base_arguments,
initialize: #module_ident::#init_initalize_arguments,
new: #module_ident::#init_new_arguments,
}
}
},
parse_quote_spanned! {
constructor.imp.span() =>
#[doc(hidden)]
#[allow(unused_variables)]
pub fn #new_rust(new_arguments: #new_arguments_rust) -> std::boxed::Box<#rust_struct_name_rust> {
std::boxed::Box::new(<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::new((#(#extract_new_arguments,)*)))
pub fn #new_rust(new_arguments: #module_ident::#new_arguments_rust) -> std::boxed::Box<#rust_struct_name_rust> {
std::boxed::Box::new(<#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::new((#(#extract_new_arguments,)*)))
}
},
parse_quote_spanned! {
constructor.imp.span() =>
#[doc(hidden)]
#[allow(unused_variables)]
pub fn #initialize_rust(
qobject: core::pin::Pin<&mut #qobject_name_rust>,
initialize_arguments: #initialize_arguments_rust
qobject: core::pin::Pin<&mut #qobject_name_rust_qualified>,
initialize_arguments: #module_ident::#initialize_arguments_rust
) {
<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize(
<#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::initialize(
qobject,
(#(#extract_initialize_arguments,)*));
}
Expand All @@ -320,6 +347,8 @@ mod tests {
use super::*;
use crate::tests::assert_tokens_eq;

use quote::format_ident;

fn mock_constructor() -> Constructor {
Constructor {
new_arguments: vec![],
Expand All @@ -339,8 +368,15 @@ mod tests {
NamespaceName::from_pair_str("ffi", &format_ident!("MyObject"))
}

fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObjectBlocks {
generate(constructors, &mock_name(), &mock_namespace()).unwrap()
fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObject {
generate(
constructors,
&mock_name(),
&mock_namespace(),
&BTreeMap::<Ident, Path>::default(),
&format_ident!("ffi"),
)
.unwrap()
}

#[test]
Expand Down Expand Up @@ -394,7 +430,7 @@ mod tests {
// This is called by the `multiple_constructors` test so we don't have to
// assert this in two separate tests.
fn assert_empty_constructor_blocks(
blocks: &GeneratedRustQObjectBlocks,
blocks: &GeneratedRustQObject,
namespace_attr: &TokenStream,
) {
assert_tokens_eq(
Expand Down Expand Up @@ -450,17 +486,17 @@ mod tests {
&blocks.cxx_qt_mod_contents[0],
quote! {
#[doc(hidden)]
pub fn route_arguments_my_object_0() -> CxxQtConstructorArgumentsMyObject0
pub fn route_arguments_my_object_0() -> ffi::CxxQtConstructorArgumentsMyObject0
{
#[allow(unused_variables)]
#[allow(clippy::let_unit_value)]
let (new_arguments, base_arguments, initialize_arguments) =
<MyObject as cxx_qt::Constructor<()> >::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 },
}
}
},
Expand All @@ -470,7 +506,7 @@ mod tests {
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
pub fn new_rs_my_object_0(new_arguments: CxxQtConstructorNewArgumentsMyObject0) -> std::boxed::Box<MyObjectRust> {
pub fn new_rs_my_object_0(new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject0) -> std::boxed::Box<MyObjectRust> {
std::boxed::Box::new(
<MyObject as cxx_qt::Constructor<()> >::new(())
)
Expand All @@ -484,18 +520,15 @@ mod tests {
#[allow(unused_variables)]
pub fn initialize_my_object_0(
qobject: core::pin::Pin<&mut MyObject>,
initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0)
initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject0)
{
<MyObject as cxx_qt::Constructor<()> >::initialize(qobject, ());
}
},
);
}

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],
Expand Down Expand Up @@ -571,24 +604,24 @@ mod tests {
&blocks.cxx_qt_mod_contents[3],
quote! {
#[doc(hidden)]
pub fn route_arguments_my_object_1(arg0: *const QObject) -> CxxQtConstructorArgumentsMyObject1
pub fn route_arguments_my_object_1(arg0: *const QObject) -> ffi::CxxQtConstructorArgumentsMyObject1
{
#[allow(unused_variables)]
#[allow(clippy::let_unit_value)]
let (new_arguments, base_arguments, initialize_arguments) =
<MyObject as cxx_qt::Constructor<(*const QObject,)> >::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,
},
}
Expand All @@ -600,7 +633,7 @@ mod tests {
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
pub fn new_rs_my_object_1(new_arguments: CxxQtConstructorNewArgumentsMyObject1) -> std::boxed::Box<MyObjectRust> {
pub fn new_rs_my_object_1(new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject1) -> std::boxed::Box<MyObjectRust> {
std::boxed::Box::new(
<MyObject as cxx_qt::Constructor<(*const QObject,)> >::new(
(new_arguments.arg0,)))
Expand All @@ -614,7 +647,7 @@ mod tests {
#[allow(unused_variables)]
pub fn initialize_my_object_1(
qobject: core::pin::Pin<&mut MyObject>,
initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject1)
initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject1)
{
<MyObject as cxx_qt::Constructor<(*const QObject,)> >::initialize(
qobject,
Expand Down
Loading