Skip to content

Commit

Permalink
Remove RustFragmentPair struct
Browse files Browse the repository at this point in the history
  • Loading branch information
BenFordTytherington committed Jan 16, 2025
1 parent e84662a commit 109b6c8
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 261 deletions.
46 changes: 14 additions & 32 deletions crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,12 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{
generator::{naming::qobject::QObjectNames, rust::fragment::GeneratedRustFragment},
naming::TypeNames,
};
use quote::quote;
use syn::Result;
use crate::{generator::naming::qobject::QObjectNames, naming::TypeNames};
use syn::{parse_quote, Result};

use super::fragment::RustFragmentPair;

pub fn generate(
qobject_names: &QObjectNames,
type_names: &TypeNames,
) -> Result<GeneratedRustFragment> {
let mut blocks = GeneratedRustFragment::default();
use super::fragment::GeneratedRustFragment;

pub fn generate(qobject_names: &QObjectNames, type_names: &TypeNames) -> Result<GeneratedRustFragment> {
let cpp_struct_ident = &qobject_names.name.rust_unqualified();
let rust_struct_ident = &qobject_names.rust_struct.rust_unqualified();
let (rust_fn_name, rust_fn_attrs, rust_fn_qualified) = qobject_names
Expand All @@ -30,25 +21,25 @@ pub fn generate(

let qualified_impl = type_names.rust_qualified(cpp_struct_ident)?;

let fragment = RustFragmentPair {
cxx_bridge: vec![
quote! {
Ok(GeneratedRustFragment {
cxx_mod_contents: vec![
parse_quote! {
unsafe extern "C++" {
#[doc(hidden)]
#(#rust_fn_attrs)*
fn #rust_fn_name(outer: &#cpp_struct_ident) -> &#rust_struct_ident;
}
},
quote! {
parse_quote! {
unsafe extern "C++" {
#[doc(hidden)]
#(#rust_mut_fn_attrs)*
fn #rust_mut_fn_name(outer: Pin<&mut #cpp_struct_ident>) -> Pin<&mut #rust_struct_ident>;
}
},
],
implementation: vec![
quote! {
cxx_qt_mod_contents: vec![
parse_quote! {
impl ::core::ops::Deref for #qualified_impl {
type Target = #rust_struct_ident;

Expand All @@ -57,7 +48,7 @@ pub fn generate(
}
}
},
quote! {
parse_quote! {
impl ::cxx_qt::CxxQtType for #qualified_impl {
type Rust = #rust_struct_ident;

Expand All @@ -71,25 +62,16 @@ pub fn generate(
}
},
],
};

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;
use crate::tests::assert_tokens_eq;
use quote::quote;

#[test]
fn test_generate_rust_cxxqttype() {
Expand Down
19 changes: 9 additions & 10 deletions crates/cxx-qt-gen/src/generator/rust/externcxxqt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use crate::{
generator::rust::{
fragment::{GeneratedRustFragment, RustFragmentPair},
fragment::GeneratedRustFragment,
signals::generate_rust_signal,
},
naming::TypeNames,
parser::externcxxqt::ParsedExternCxxQt,
syntax::path::path_compare_str,
};
use quote::quote;
use syn::{Attribute, Result};
use syn::{parse_quote, Attribute, Result};

impl GeneratedRustFragment {
pub fn from_extern_cxx_qt(
Expand Down Expand Up @@ -66,20 +66,19 @@ impl GeneratedRustFragment {
})
.collect::<Vec<_>>();

let fragment = RustFragmentPair {
cxx_bridge: vec![quote! {
generated.append(&mut GeneratedRustFragment {
cxx_mod_contents: vec![
parse_quote! {
#extern_block_namespace
#unsafety extern "C++" {
#(#items)*

#(#types)*
}
}],
implementation: vec![],
};
generated
.cxx_mod_contents
.append(&mut fragment.cxx_bridge_as_items()?);
}
],
cxx_qt_mod_contents: vec![],
});

// Build the signals
for signal in &extern_cxxqt_block.signals {
Expand Down
25 changes: 1 addition & 24 deletions crates/cxx-qt-gen/src/generator/rust/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use proc_macro2::TokenStream;
use syn::{Item, Result};
use syn::Item;

#[derive(Default, Eq, PartialEq, Debug)]
pub struct GeneratedRustFragment {
Expand All @@ -21,25 +20,3 @@ impl GeneratedRustFragment {
.append(&mut other.cxx_qt_mod_contents);
}
}

/// A generic Rust CXX bridge definition and the corresponding implementation
pub struct RustFragmentPair {
pub cxx_bridge: Vec<TokenStream>,
pub implementation: Vec<TokenStream>,
}

impl RustFragmentPair {
pub fn cxx_bridge_as_items(&self) -> Result<Vec<Item>> {
self.cxx_bridge
.iter()
.map(|tokens| syn::parse2(tokens.clone()))
.collect()
}

pub fn implementation_as_items(&self) -> Result<Vec<Item>> {
self.implementation
.iter()
.map(|tokens| syn::parse2(tokens.clone()))
.collect()
}
}
55 changes: 25 additions & 30 deletions crates/cxx-qt-gen/src/generator/rust/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use crate::generator::rust::get_params_tokens;
use crate::{
generator::{
naming::qobject::QObjectNames,
rust::fragment::{GeneratedRustFragment, RustFragmentPair},
rust::fragment::GeneratedRustFragment,
},
parser::method::ParsedMethod,
};
use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, Result};
use quote::quote;
use syn::{parse_quote_spanned, spanned::Spanned, Result};

pub fn generate_rust_methods(
invokables: &Vec<&ParsedMethod>,
Expand Down Expand Up @@ -43,34 +43,29 @@ pub fn generate_rust_methods(
let cfgs = &invokable.cfgs;
let cxx_namespace = qobject_names.namespace_tokens();

let fragment = RustFragmentPair {
cxx_bridge: vec![quote_spanned! {
invokable.method.span() =>
// Note: extern "Rust" block does not need to be unsafe
extern "Rust" {
// Note that we are exposing a Rust method on the C++ type to C++
//
// CXX ends up generating the source, then we generate the matching header.
#[cxx_name = #invokable_ident_cpp]
// Needed for QObjects to have a namespace on their type or extern block
//
// A Namespace from cxx_qt::bridge would be automatically applied to all children
// but to apply it to only certain types, it is needed here too
#cxx_namespace
#(#cfgs)*
#[doc(hidden)]
#unsafe_call fn #invokable_ident_rust(#parameter_signatures) #return_type;
generated.append(&mut GeneratedRustFragment {
cxx_mod_contents: vec![
parse_quote_spanned! {
invokable.method.span() =>
// Note: extern "Rust" block does not need to be unsafe
extern "Rust" {
// Note that we are exposing a Rust method on the C++ type to C++
//
// CXX ends up generating the source, then we generate the matching header.
#[cxx_name = #invokable_ident_cpp]
// Needed for QObjects to have a namespace on their type or extern block
//
// A Namespace from cxx_qt::bridge would be automatically applied to all children
// but to apply it to only certain types, it is needed here too
#cxx_namespace
#(#cfgs)*
#[doc(hidden)]
#unsafe_call fn #invokable_ident_rust(#parameter_signatures) #return_type;
}
}
}],
implementation: vec![],
};

generated
.cxx_mod_contents
.append(&mut fragment.cxx_bridge_as_items()?);
generated
.cxx_qt_mod_contents
.append(&mut fragment.implementation_as_items()?);
],
cxx_qt_mod_contents: vec![],
});
}

Ok(generated)
Expand Down
55 changes: 28 additions & 27 deletions crates/cxx-qt-gen/src/generator/rust/property/getter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,23 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::generator::rust::fragment::GeneratedRustFragment;
use crate::{
generator::{
naming::{
property::{NameState, QPropertyNames},
qobject::QObjectNames,
},
rust::fragment::RustFragmentPair,
generator::naming::{
property::{NameState, QPropertyNames},
qobject::QObjectNames,
},
naming::rust::syn_type_cxx_bridge_to_qualified,
naming::TypeNames,
};
use quote::quote;
use syn::{Result, Type};
use syn::{parse_quote, Result, Type};

pub fn generate(
idents: &QPropertyNames,
qobject_names: &QObjectNames,
cxx_ty: &Type,
type_names: &TypeNames,
) -> Result<Option<RustFragmentPair>> {
) -> Result<Option<GeneratedRustFragment>> {
if let NameState::Auto(getter) = &idents.getter {
let cpp_class_name_rust = &qobject_names.name.rust_unqualified();
let getter_cpp = getter.cxx_unqualified();
Expand All @@ -34,27 +31,31 @@ pub fn generate(

let cxx_namespace = qobject_names.namespace_tokens();

Ok(Some(RustFragmentPair {
cxx_bridge: vec![quote! {
extern "Rust" {
#[cxx_name = #getter_cpp]
// Needed for QObjects to have a namespace on their type or extern block
//
// A Namespace from cxx_qt::bridge would be automatically applied to all children
// but to apply it to only certain types, it is needed here too
#cxx_namespace
unsafe fn #getter_rust<'a>(self: &'a #cpp_class_name_rust) -> &'a #cxx_ty;
Ok(Some(GeneratedRustFragment {
cxx_mod_contents: vec![
parse_quote! {
extern "Rust" {
#[cxx_name = #getter_cpp]
// Needed for QObjects to have a namespace on their type or extern block
//
// A Namespace from cxx_qt::bridge would be automatically applied to all children
// but to apply it to only certain types, it is needed here too
#cxx_namespace
unsafe fn #getter_rust<'a>(self: &'a #cpp_class_name_rust) -> &'a #cxx_ty;
}
}
}],
implementation: vec![quote! {
impl #qualified_impl {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = #ident_str]
pub fn #getter_rust(&self) -> &#qualified_ty {
&self.#ident
],
cxx_qt_mod_contents: vec![
parse_quote! {
impl #qualified_impl {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = #ident_str]
pub fn #getter_rust(&self) -> &#qualified_ty {
&self.#ident
}
}
}
}],
],
}))
} else {
Ok(None)
Expand Down
18 changes: 4 additions & 14 deletions crates/cxx-qt-gen/src/generator/rust/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,12 @@ pub fn generate_rust_properties(
for property in properties {
let idents = QPropertyNames::try_from_property(property, structured_qobject)?;

if let Some(getter) = getter::generate(&idents, qobject_names, &property.ty, type_names)? {
generated
.cxx_mod_contents
.append(&mut getter.cxx_bridge_as_items()?);
generated
.cxx_qt_mod_contents
.append(&mut getter.implementation_as_items()?);
if let Some(mut getter) = getter::generate(&idents, qobject_names, &property.ty, type_names)? {
generated.append(&mut getter);
};

if let Some(setter) = setter::generate(&idents, qobject_names, &property.ty, type_names)? {
generated
.cxx_mod_contents
.append(&mut setter.cxx_bridge_as_items()?);
generated
.cxx_qt_mod_contents
.append(&mut setter.implementation_as_items()?);
if let Some(mut setter) = setter::generate(&idents, qobject_names, &property.ty, type_names)? {
generated.append(&mut setter);
}

if let Some(notify) = signal::generate(&idents, qobject_names) {
Expand Down
Loading

0 comments on commit 109b6c8

Please sign in to comment.