From da02e0db2b472adf4937c53e445e696a6fb0cc85 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Thu, 29 Aug 2024 10:46:36 +0100 Subject: [PATCH 1/8] Refactor ParsedMethod and ParsedInheritedMethod to have docs fields like ParsedSignal - ParsedSignal had a `docs: Vec` field, and it seemed appropriate to add this to method and inherited methods too Is this the intended use? --- crates/cxx-qt-gen/src/generator/cpp/method.rs | 1 + crates/cxx-qt-gen/src/generator/naming/method.rs | 1 + crates/cxx-qt-gen/src/generator/rust/inherit.rs | 4 ++++ crates/cxx-qt-gen/src/generator/rust/method.rs | 12 +++++++----- crates/cxx-qt-gen/src/parser/inherit.rs | 10 +++++++++- crates/cxx-qt-gen/src/parser/method.rs | 11 ++++++++++- crates/cxx-qt-gen/src/parser/signals.rs | 2 +- crates/cxx-qt-gen/test_outputs/inheritance.rs | 6 ++---- crates/cxx-qt-gen/test_outputs/invokables.rs | 11 ----------- .../test_outputs/passthrough_and_naming.rs | 2 -- crates/cxx-qt-gen/test_outputs/properties.rs | 3 --- crates/cxx-qt-gen/test_outputs/qenum.rs | 1 - crates/cxx-qt-gen/test_outputs/signals.rs | 1 - 13 files changed, 35 insertions(+), 30 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/cpp/method.rs b/crates/cxx-qt-gen/src/generator/cpp/method.rs index 3d701b72e..69a2f173f 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/method.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/method.rs @@ -328,6 +328,7 @@ mod tests { None, ) .unwrap(), + docs: vec![], }; let invokables = vec![&method]; let qobject_idents = create_qobjectname(); diff --git a/crates/cxx-qt-gen/src/generator/naming/method.rs b/crates/cxx-qt-gen/src/generator/naming/method.rs index 5a47150e7..031e0e214 100644 --- a/crates/cxx-qt-gen/src/generator/naming/method.rs +++ b/crates/cxx-qt-gen/src/generator/naming/method.rs @@ -59,6 +59,7 @@ mod tests { is_qinvokable: true, name: Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None) .unwrap(), + docs: vec![], }; let invokable = QMethodName::try_from(&parsed).unwrap(); diff --git a/crates/cxx-qt-gen/src/generator/rust/inherit.rs b/crates/cxx-qt-gen/src/generator/rust/inherit.rs index cc1a90e09..8d7906f99 100644 --- a/crates/cxx-qt-gen/src/generator/rust/inherit.rs +++ b/crates/cxx-qt-gen/src/generator/rust/inherit.rs @@ -45,11 +45,15 @@ pub fn generate( std::mem::swap(&mut unsafe_call, &mut unsafe_block); } let attrs = &method.method.attrs; + + let doc_comments = &method.docs; + syn::parse2(quote_spanned! { method.method.span() => #unsafe_block extern "C++" { #(#attrs)* #[cxx_name = #cxx_name_string] + #(#doc_comments)* #unsafe_call fn #ident(#self_param, #(#parameters),*) #return_type; } }) diff --git a/crates/cxx-qt-gen/src/generator/rust/method.rs b/crates/cxx-qt-gen/src/generator/rust/method.rs index 8a8d687c6..4955733d0 100644 --- a/crates/cxx-qt-gen/src/generator/rust/method.rs +++ b/crates/cxx-qt-gen/src/generator/rust/method.rs @@ -43,6 +43,8 @@ pub fn generate_rust_methods( std::mem::swap(&mut unsafe_call, &mut unsafe_block); } + let doc_comments = &invokable.docs; + let fragment = RustFragmentPair { cxx_bridge: vec![quote_spanned! { invokable.method.span() => @@ -51,7 +53,7 @@ pub fn generate_rust_methods( // 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. - #[doc(hidden)] + #(#doc_comments)* #[cxx_name = #wrapper_ident_cpp] // TODO: Add #[namespace] of the QObject #unsafe_call fn #invokable_ident_rust(#parameter_signatures) #return_type; @@ -107,6 +109,7 @@ mod tests { None, ) .unwrap(), + docs: vec![], }, ParsedMethod { method: method2.clone(), @@ -126,6 +129,7 @@ mod tests { None, ) .unwrap(), + docs: vec![], }, ParsedMethod { method: method3.clone(), @@ -145,6 +149,7 @@ mod tests { None, ) .unwrap(), + docs: vec![], }, ParsedMethod { method: method4.clone(), @@ -164,6 +169,7 @@ mod tests { None, ) .unwrap(), + docs: vec![], }, ]; let qobject_idents = create_qobjectname(); @@ -179,7 +185,6 @@ mod tests { &generated.cxx_mod_contents[0], quote! { extern "Rust" { - #[doc(hidden)] #[cxx_name = "voidInvokableWrapper"] fn void_invokable(self: &MyObject); } @@ -191,7 +196,6 @@ mod tests { &generated.cxx_mod_contents[1], quote! { extern "Rust" { - #[doc(hidden)] #[cxx_name = "trivialInvokableWrapper"] fn trivial_invokable(self: &MyObject, param: i32) -> i32; } @@ -203,7 +207,6 @@ mod tests { &generated.cxx_mod_contents[2], quote! { extern "Rust" { - #[doc(hidden)] #[cxx_name = "opaqueInvokableWrapper"] fn opaque_invokable(self: Pin<&mut MyObject>, param: &QColor) -> UniquePtr; } @@ -215,7 +218,6 @@ mod tests { &generated.cxx_mod_contents[3], quote! { extern "Rust" { - #[doc(hidden)] #[cxx_name = "unsafeInvokableWrapper"] unsafe fn unsafe_invokable(self:&MyObject, param: *mut T) -> *mut T; } diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index 67e27fdde..3e3643078 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -11,7 +11,7 @@ use crate::{ }, }; use quote::format_ident; -use syn::{spanned::Spanned, Error, ForeignItemFn, Ident, Result}; +use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result}; /// Describes a method found in an extern "RustQt" with #[inherit] pub struct ParsedInheritedMethod { @@ -27,6 +27,8 @@ pub struct ParsedInheritedMethod { pub parameters: Vec, /// the name of the function in Rust, as well as C++ pub ident: Name, + /// All the docs (each line) of the inherited method + pub docs: Vec, } impl ParsedInheritedMethod { @@ -51,6 +53,11 @@ impl ParsedInheritedMethod { ident = ident.with_cxx_name(expr_to_string(&attr.meta.require_name_value()?.value)?); } + let mut docs = vec![]; + while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { + docs.push(doc); + } + let safe = method.sig.unsafety.is_none(); Ok(Self { @@ -60,6 +67,7 @@ impl ParsedInheritedMethod { parameters, ident, safe, + docs, }) } diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index a84fe8bfb..98cb3e719 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -9,7 +9,7 @@ use crate::{ syntax::{attribute::attribute_take_path, foreignmod, safety::Safety, types}, }; use std::collections::HashSet; -use syn::{spanned::Spanned, Error, ForeignItemFn, Ident, Result}; +use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result}; #[cfg(test)] use quote::format_ident; @@ -50,6 +50,8 @@ pub struct ParsedMethod { pub is_qinvokable: bool, /// The rust and cxx name of the function pub name: Name, + /// All the docs (each line) of the method + pub docs: Vec, } impl ParsedMethod { @@ -94,6 +96,11 @@ impl ParsedMethod { )); } + let mut docs = vec![]; + while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { + docs.push(doc); + } + Ok(ParsedMethod { method, qobject_ident, @@ -103,6 +110,7 @@ impl ParsedMethod { safe, is_qinvokable, name, + docs, }) } @@ -121,6 +129,7 @@ impl ParsedMethod { is_qinvokable: true, name: Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None) .unwrap(), + docs: vec![], } } diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index 541996fcc..343c52d89 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -34,7 +34,7 @@ pub struct ParsedSignal { pub inherit: bool, /// Whether the signal is private pub private: bool, - /// All the doc attributes (each line) of the Signal + /// All the doc attributes (each line) of the signal pub docs: Vec, } diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index fbf0daddb..f213af3e7 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -34,23 +34,21 @@ mod inheritance { type MyObjectRust; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "dataWrapper"] fn data(self: &MyObject, _index: &QModelIndex, _role: i32) -> QVariant; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "hasChildrenWrapper"] fn has_children(self: &MyObject, _parent: &QModelIndex) -> bool; } unsafe extern "C++" { - #[doc = " Inherited hasChildren from the base class"] #[cxx_name = "hasChildrenCxxQtInherit"] + #[doc = " Inherited hasChildren from the base class"] fn has_children_super(self: &MyObject, parent: &QModelIndex) -> bool; } extern "C++" { - #[doc = " Inherited fetchMore from the base class"] #[cxx_name = "fetchMoreCxxQtInherit"] + #[doc = " Inherited fetchMore from the base class"] unsafe fn fetch_more(self: Pin<&mut MyObject>, index: &QModelIndex); } extern "Rust" { diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index 4d43f4ee4..eb1dba81c 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -41,57 +41,46 @@ mod ffi { type MyObjectRust; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "cppMethodWrapper"] fn cpp_method(self: &MyObject); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableWrapper"] fn invokable(self: &MyObject); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableMutableWrapper"] fn invokable_mutable(self: Pin<&mut MyObject>); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableParametersWrapper"] fn invokable_parameters(self: &MyObject, opaque: &QColor, trivial: &QPoint, primitive: i32); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableReturnOpaqueWrapper"] fn invokable_return_opaque(self: Pin<&mut MyObject>) -> UniquePtr; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableReturnTrivialWrapper"] fn invokable_return_trivial(self: Pin<&mut MyObject>) -> QPoint; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableFinalWrapper"] fn invokable_final(self: &MyObject); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableOverrideWrapper"] fn invokable_override(self: &MyObject); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableVirtualWrapper"] fn invokable_virtual(self: &MyObject); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableResultTupleWrapper"] fn invokable_result_tuple(self: &MyObject) -> Result<()>; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableResultTypeWrapper"] fn invokable_result_type(self: &MyObject) -> Result; } 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 afb70e660..c160c1eb3 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -124,7 +124,6 @@ pub mod ffi { ); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableNameWrapper"] fn invokable_name(self: Pin<&mut MyObject>); } @@ -257,7 +256,6 @@ pub mod ffi { ); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableNameWrapper"] fn invokable_name(self: Pin<&mut SecondObject>); } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 4e30a6020..67b5303e3 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -187,17 +187,14 @@ mod ffi { ); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "myGetterWrapper"] fn my_getter(self: &MyObject) -> i32; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "MyCustomSetterWrapper"] fn my_setter(self: Pin<&mut MyObject>, value: i32); } extern "Rust" { - #[doc(hidden)] #[cxx_name = "myResetFnWrapper"] fn myResetFn(self: Pin<&mut MyObject>); } diff --git a/crates/cxx-qt-gen/test_outputs/qenum.rs b/crates/cxx-qt-gen/test_outputs/qenum.rs index 01c49f0e6..75e807843 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.rs +++ b/crates/cxx-qt-gen/test_outputs/qenum.rs @@ -78,7 +78,6 @@ mod ffi { type MyObjectRust; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "myInvokableWrapper"] fn my_invokable(self: &MyObject, qenum: MyEnum, other_qenum: MyOtherEnum); } diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 263d973b1..f92678d9a 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -35,7 +35,6 @@ mod ffi { type MyObjectRust; } extern "Rust" { - #[doc(hidden)] #[cxx_name = "invokableWrapper"] fn invokable(self: Pin<&mut MyObject>); } From 27a619b4ed7a9046f667d1a2fe1d69e40b68a3ea Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Thu, 29 Aug 2024 10:58:14 +0100 Subject: [PATCH 2/8] Rename field in ParsedInheritedMethod to name, to be consistent with other structs --- crates/cxx-qt-gen/src/generator/cpp/inherit.rs | 2 +- crates/cxx-qt-gen/src/parser/inherit.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/cpp/inherit.rs b/crates/cxx-qt-gen/src/generator/cpp/inherit.rs index 41a8c641e..ac599fd3e 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/inherit.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/inherit.rs @@ -35,7 +35,7 @@ pub fn generate( return {base_class}::{func_ident}(args...); }}"#, mutability = if method.mutable { "" } else { " const" }, - func_ident = method.ident.cxx_unqualified(), + func_ident = method.name.cxx_unqualified(), wrapper_ident = method.wrapper_ident(), return_type = return_type.unwrap_or_else(|| "void".to_string()), base_class = base_class diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index 3e3643078..febe310f1 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -26,7 +26,7 @@ pub struct ParsedInheritedMethod { /// the parameters of the method, without the `self` argument pub parameters: Vec, /// the name of the function in Rust, as well as C++ - pub ident: Name, + pub name: Name, /// All the docs (each line) of the inherited method pub docs: Vec, } @@ -65,7 +65,7 @@ impl ParsedInheritedMethod { qobject_ident, mutable, parameters, - ident, + name: ident, safe, docs, }) @@ -73,7 +73,7 @@ impl ParsedInheritedMethod { /// the name of the wrapper function in C++ pub fn wrapper_ident(&self) -> Ident { - format_ident!("{}CxxQtInherit", self.ident.cxx_unqualified()) + format_ident!("{}CxxQtInherit", self.name.cxx_unqualified()) } } @@ -154,10 +154,10 @@ mod tests { assert_eq!(parsed.qobject_ident, format_ident!("T")); assert_eq!(parsed.parameters.len(), 2); assert_eq!( - parsed.ident.rust_unqualified().to_string(), + parsed.name.rust_unqualified().to_string(), String::from("test") ); - assert_eq!(parsed.ident.cxx_unqualified(), String::from("testFunction")); + assert_eq!(parsed.name.cxx_unqualified(), String::from("testFunction")); assert_eq!( parsed.wrapper_ident(), format_ident!("testFunctionCxxQtInherit") From 627035d4c0b70112cea5be3534e7550d4c0e0bd0 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Thu, 29 Aug 2024 12:31:43 +0100 Subject: [PATCH 3/8] Refactor some common logic used by ParsedSignal, ParsedMethod and ParsedInheritedMethod Includes introducing a struct and associated functions for the common fields, combining the common logic for parsing those fields. Also adds methods to build those types from the InvokableFields struct --- crates/cxx-qt-gen/src/parser/inherit.rs | 51 +++++++----------- crates/cxx-qt-gen/src/parser/method.rs | 71 +++++++++++++------------ crates/cxx-qt-gen/src/parser/mod.rs | 58 +++++++++++++++++++- crates/cxx-qt-gen/src/parser/signals.rs | 64 +++++++++++----------- 4 files changed, 146 insertions(+), 98 deletions(-) diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index febe310f1..629a4a8e9 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -3,15 +3,14 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, - syntax::{ - attribute::attribute_take_path, expr::expr_to_string, foreignmod, safety::Safety, types, - }, + syntax::{attribute::attribute_take_path, expr::expr_to_string, safety::Safety}, }; use quote::format_ident; -use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result}; +use syn::{Attribute, ForeignItemFn, Ident, Result}; /// Describes a method found in an extern "RustQt" with #[inherit] pub struct ParsedInheritedMethod { @@ -33,42 +32,32 @@ pub struct ParsedInheritedMethod { impl ParsedInheritedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { - if safety == Safety::Unsafe && method.sig.unsafety.is_none() { - return Err(Error::new( - method.span(), - "Inherited methods must be marked as unsafe or wrapped in an `unsafe extern \"RustQt\"` block!", - )); - } - - let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; - let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; - let mutable = mutability.is_some(); + check_safety(&method, &safety)?; - let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; + let docs = separate_docs(&mut method); + let invokable_fields = extract_common_fields(&method, docs)?; - let mut ident = + let mut name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; + // This block seems unnecessary but removing it causes one cxx_name attr in test_outputs to lose the CxxQtInherit suffix if let Some(attr) = attribute_take_path(&mut method.attrs, &["cxx_name"]) { - ident = ident.with_cxx_name(expr_to_string(&attr.meta.require_name_value()?.value)?); - } - - let mut docs = vec![]; - while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { - docs.push(doc); + name = name.with_cxx_name(expr_to_string(&attr.meta.require_name_value()?.value)?); } - let safe = method.sig.unsafety.is_none(); + Ok(Self::from_invokable_fields(invokable_fields, method, name)) + } - Ok(Self { + fn from_invokable_fields(fields: InvokableFields, method: ForeignItemFn, name: Name) -> Self { + Self { method, - qobject_ident, - mutable, - parameters, - name: ident, - safe, - docs, - }) + qobject_ident: fields.qobject_ident, + mutable: fields.mutable, + safe: fields.safe, + parameters: fields.parameters, + name, + docs: fields.docs, + } } /// the name of the wrapper function in C++ diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index 98cb3e719..58c748ca8 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -6,11 +6,12 @@ use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, - syntax::{attribute::attribute_take_path, foreignmod, safety::Safety, types}, + syntax::{attribute::attribute_take_path, safety::Safety}, }; use std::collections::HashSet; -use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result}; +use syn::{Attribute, Error, ForeignItemFn, Ident, Result}; +use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; #[cfg(test)] use quote::format_ident; @@ -56,10 +57,17 @@ pub struct ParsedMethod { impl ParsedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { - if safety == Safety::Unsafe && method.sig.unsafety.is_none() { - return Err(Error::new( - method.span(), - "Invokable methods must be marked as unsafe or wrapped in an `unsafe extern \"RustQt\"` block!", + check_safety(&method, &safety)?; + + let docs = separate_docs(&mut method); + let invokable_fields = extract_common_fields(&method, docs)?; + + let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; + + if name.namespace().is_some() { + return Err(Error::new_spanned( + method.sig.ident, + "Methods / QInvokables cannot have a namespace attribute", )); } @@ -78,40 +86,33 @@ impl ParsedMethod { } } - // Determine if the invokable is mutable - let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; - let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; - let mutable = mutability.is_some(); - - let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; - - let safe = method.sig.unsafety.is_none(); - - let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; - - if name.namespace().is_some() { - return Err(Error::new_spanned( - method.sig.ident, - "Methods / QInvokables cannot have a namespace attribute", - )); - } - - let mut docs = vec![]; - while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { - docs.push(doc); - } + Ok(ParsedMethod::from_invokable_fields( + invokable_fields, + method, + name, + specifiers, + is_qinvokable, + )) + } - Ok(ParsedMethod { + fn from_invokable_fields( + fields: InvokableFields, + method: ForeignItemFn, + name: Name, + specifiers: HashSet, + is_qinvokable: bool, + ) -> Self { + Self { method, - qobject_ident, - mutable, - parameters, + qobject_ident: fields.qobject_ident, + mutable: fields.mutable, + safe: fields.safe, + parameters: fields.parameters, specifiers, - safe, is_qinvokable, name, - docs, - }) + docs: fields.docs, + } } #[cfg(test)] diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 3a57501db..905c55c53 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -15,6 +15,9 @@ pub mod qnamespace; pub mod qobject; pub mod signals; +use crate::parser::parameter::ParsedFunctionParameter; +use crate::syntax::safety::Safety; +use crate::syntax::{foreignmod, types}; use crate::{ // Used for error handling when resolving the namespace of the qenum. naming::TypeNames, @@ -25,9 +28,62 @@ use syn::{ punctuated::Punctuated, spanned::Spanned, token::{Brace, Semi}, - Error, Ident, Item, ItemMod, Meta, Result, Token, + Attribute, Error, ForeignItemFn, Ident, Item, ItemMod, Meta, Result, Token, }; +fn check_safety(method: &ForeignItemFn, safety: &Safety) -> Result<()> { + if safety == &Safety::Unsafe && method.sig.unsafety.is_none() { + Err(Error::new( + method.span(), + "Invokables must be marked as unsafe or wrapped in an `unsafe extern \"RustQt\"` block!", + )) + } else { + Ok(()) + } +} + +/// Struct with common fields between Invokable types. +/// These types are ParsedSignal, ParsedMethod and ParsedInheritedMethod +pub struct InvokableFields { + qobject_ident: Ident, + mutable: bool, + parameters: Vec, + safe: bool, + docs: Vec, +} + +/// Function for creating an [InvokableFields] from a method and docs. +/// These fields are shared by ParsedSignal, ParsedMethod and ParsedInheritedMethod so grouped into common logic. +pub fn extract_common_fields( + method: &ForeignItemFn, + docs: Vec, +) -> Result { + let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; + let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; + let mutable = mutability.is_some(); + + let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; + let safe = method.sig.unsafety.is_none(); + Ok(InvokableFields { + qobject_ident, + mutable, + parameters, + safe, + docs, + }) +} + +/// Iterate the attributes of the method to extract Doc attributes (doc comments are parsed as this) +/// +/// Note: This modifies the method by removing those doc attributes +pub fn separate_docs(method: &mut ForeignItemFn) -> Vec { + let mut docs = vec![]; + while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { + docs.push(doc); + } + docs +} + /// 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. /// diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index 343c52d89..a99e8c82c 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -6,12 +6,11 @@ use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, - syntax::{ - attribute::attribute_take_path, foreignmod, path::path_compare_str, safety::Safety, types, - }, + syntax::{attribute::attribute_take_path, path::path_compare_str, safety::Safety}, }; use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result, Visibility}; +use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; #[cfg(test)] use quote::format_ident; @@ -77,24 +76,10 @@ impl ParsedSignal { } pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { - if safety == Safety::Unsafe && method.sig.unsafety.is_none() { - return Err(Error::new( - method.span(), - "qsignals methods must be marked as unsafe or wrapped in an `unsafe extern \"RustQt\"` block!", - )); - } - - let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; - let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; - let mutable = mutability.is_some(); - if !mutable { - return Err(Error::new( - method.span(), - "signals must be mutable, use Pin<&mut T> instead of T for the self type", - )); - } + check_safety(&method, &safety)?; - let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; + let docs = separate_docs(&mut method); + let invokable_fields = extract_common_fields(&method, docs)?; let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; @@ -105,30 +90,47 @@ impl ParsedSignal { )); } - let mut docs = vec![]; - while let Some(doc) = attribute_take_path(&mut method.attrs, &["doc"]) { - docs.push(doc); + if !invokable_fields.mutable { + return Err(Error::new( + method.span(), + "signals must be mutable, use Pin<&mut T> instead of T for the self type", + )); } let inherit = attribute_take_path(&mut method.attrs, &["inherit"]).is_some(); - let safe = method.sig.unsafety.is_none(); let private = if let Visibility::Restricted(vis_restricted) = &method.vis { path_compare_str(&vis_restricted.path, &["self"]) } else { false }; - Ok(Self { + Ok(Self::from_invokable_fields( + invokable_fields, method, - qobject_ident, - mutable, - parameters, name, - safe, inherit, private, - docs, - }) + )) + } + + fn from_invokable_fields( + fields: InvokableFields, + method: ForeignItemFn, + name: Name, + inherit: bool, + private: bool, + ) -> Self { + Self { + method, + qobject_ident: fields.qobject_ident, + mutable: fields.mutable, + safe: fields.safe, + parameters: fields.parameters, + name, + inherit, + private, + docs: fields.docs, + } } } From 02b67fe929c3e0dbc33d598b858beffd14767ec0 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Fri, 30 Aug 2024 10:02:45 +0100 Subject: [PATCH 4/8] Add inherited methods to the method_lookup function, as a fallback. e.g. Function searches for non-inherited methods first --- .../src/generator/structuring/mod.rs | 25 +++++++++++++++++++ .../src/generator/structuring/qobject.rs | 10 +++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/cxx-qt-gen/src/generator/structuring/mod.rs b/crates/cxx-qt-gen/src/generator/structuring/mod.rs index 1845b2408..e60d84c9e 100644 --- a/crates/cxx-qt-gen/src/generator/structuring/mod.rs +++ b/crates/cxx-qt-gen/src/generator/structuring/mod.rs @@ -210,6 +210,31 @@ mod tests { .is_err()); } + #[test] + fn test_inherited_lookup() { + let module = parse_quote! { + #[cxx_qt::bridge] + mod ffi { + extern "RustQt" { + #[qobject] + type MyObject = super::MyObjectRust; + } + + unsafe extern "RustQt" { + #[qinvokable] + #[inherit] + fn test_fn(self: Pin<&mut MyObject>); + } + } + }; + + let parser = Parser::from(module).unwrap(); + let structures = Structures::new(&parser.cxx_qt_data).unwrap(); + + let qobject = structures.qobjects.first().unwrap(); + assert!(qobject.method_lookup(&format_ident!("test_fn")).is_ok()); + } + #[test] fn test_structures() { let module: ItemMod = parse_quote! { diff --git a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs index 5436263f3..94a5074db 100644 --- a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs @@ -37,16 +37,24 @@ impl<'a> StructuredQObject<'a> { } } + /// Returns the name of the method with the provided Rust ident if it exists, or an error pub fn method_lookup(&self, id: &Ident) -> Result { - // TODO account for inherited methods too since those are in a different vector self.methods .iter() .map(|method| &method.name) .find(|name| name.rust_unqualified() == id) .cloned() + .or_else(|| { + self.inherited_methods + .iter() + .map(|inherited_method| &inherited_method.name) + .find(|name| name.rust_unqualified() == id) + .cloned() + }) .ok_or_else(|| Error::new_spanned(id, format!("Method with name '{id}' not found!"))) } + /// Returns the name of the signal with the provided Rust ident if it exists, or an error pub fn signal_lookup(&self, id: &Ident) -> Result { self.signals .iter() From 2a43203b0ac5b629a0b411d6fae9f84f6e2a2c7d Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Fri, 30 Aug 2024 10:25:35 +0100 Subject: [PATCH 5/8] Refactor 3 invokable types to implement a trait, which allows lookup to be refactored - They now implement an Invokable trait which can be extended to improve shared functionality - This allowed refactoring of method and signal lookup to use a common lookup function --- .../src/generator/structuring/qobject.rs | 30 ++++++++----------- crates/cxx-qt-gen/src/parser/inherit.rs | 10 ++++++- crates/cxx-qt-gen/src/parser/method.rs | 10 ++++++- crates/cxx-qt-gen/src/parser/mod.rs | 5 ++++ crates/cxx-qt-gen/src/parser/signals.rs | 10 ++++++- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs index 94a5074db..467edfaf1 100644 --- a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs @@ -7,7 +7,7 @@ use crate::naming::Name; use crate::parser::inherit::ParsedInheritedMethod; use crate::parser::method::ParsedMethod; use crate::parser::signals::ParsedSignal; -use crate::parser::{qenum::ParsedQEnum, qobject::ParsedQObject}; +use crate::parser::{qenum::ParsedQEnum, qobject::ParsedQObject, Invokable}; use proc_macro2::Ident; use syn::{Error, Result}; @@ -21,6 +21,14 @@ pub struct StructuredQObject<'a> { pub signals: Vec<&'a ParsedSignal>, } +fn lookup(invokables: &Vec, id: &Ident) -> Option { + invokables + .iter() + .map(|invokable| invokable.name()) + .find(|name| name.rust_unqualified() == id) + .cloned() +} + impl<'a> StructuredQObject<'a> { pub fn has_qobject_name(&self, ident: &Ident) -> bool { self.declaration.name.rust_unqualified() == ident @@ -39,28 +47,14 @@ impl<'a> StructuredQObject<'a> { /// Returns the name of the method with the provided Rust ident if it exists, or an error pub fn method_lookup(&self, id: &Ident) -> Result { - self.methods - .iter() - .map(|method| &method.name) - .find(|name| name.rust_unqualified() == id) - .cloned() - .or_else(|| { - self.inherited_methods - .iter() - .map(|inherited_method| &inherited_method.name) - .find(|name| name.rust_unqualified() == id) - .cloned() - }) + lookup(&self.methods, id) + .or_else(|| lookup(&self.inherited_methods, id)) // fallback to searching inherited methods .ok_or_else(|| Error::new_spanned(id, format!("Method with name '{id}' not found!"))) } /// Returns the name of the signal with the provided Rust ident if it exists, or an error pub fn signal_lookup(&self, id: &Ident) -> Result { - self.signals - .iter() - .map(|signal| &signal.name) - .find(|name| name.rust_unqualified() == id) - .cloned() + lookup(&self.signals, id) .ok_or_else(|| Error::new_spanned(id, format!("Signal with name '{id}' not found!"))) } diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index 629a4a8e9..95649dced 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -3,7 +3,9 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; +use crate::parser::{ + check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, +}; use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, @@ -30,6 +32,12 @@ pub struct ParsedInheritedMethod { pub docs: Vec, } +impl Invokable for &ParsedInheritedMethod { + fn name(&self) -> &Name { + &self.name + } +} + impl ParsedInheritedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { check_safety(&method, &safety)?; diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index 58c748ca8..f378240ea 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -11,7 +11,9 @@ use crate::{ use std::collections::HashSet; use syn::{Attribute, Error, ForeignItemFn, Ident, Result}; -use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; +use crate::parser::{ + check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, +}; #[cfg(test)] use quote::format_ident; @@ -55,6 +57,12 @@ pub struct ParsedMethod { pub docs: Vec, } +impl Invokable for &ParsedMethod { + fn name(&self) -> &Name { + &self.name + } +} + impl ParsedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { check_safety(&method, &safety)?; diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 905c55c53..5730d7e18 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -15,6 +15,7 @@ pub mod qnamespace; pub mod qobject; pub mod signals; +use crate::naming::Name; use crate::parser::parameter::ParsedFunctionParameter; use crate::syntax::safety::Safety; use crate::syntax::{foreignmod, types}; @@ -42,6 +43,10 @@ fn check_safety(method: &ForeignItemFn, safety: &Safety) -> Result<()> { } } +pub trait Invokable { + fn name(self: &Self) -> &Name; +} + /// Struct with common fields between Invokable types. /// These types are ParsedSignal, ParsedMethod and ParsedInheritedMethod pub struct InvokableFields { diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index a99e8c82c..1a12c2c27 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -10,7 +10,9 @@ use crate::{ }; use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result, Visibility}; -use crate::parser::{check_safety, extract_common_fields, separate_docs, InvokableFields}; +use crate::parser::{ + check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, +}; #[cfg(test)] use quote::format_ident; @@ -37,6 +39,12 @@ pub struct ParsedSignal { pub docs: Vec, } +impl Invokable for &ParsedSignal { + fn name(&self) -> &Name { + &self.name + } +} + impl ParsedSignal { /// Builds a signal from a given property method pub fn from_property_method( From f499b9ab899254f65450cf2f87099773dd754dd9 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Fri, 30 Aug 2024 11:55:39 +0100 Subject: [PATCH 6/8] Move name into InvokableFields to further simplify parsing --- crates/cxx-qt-gen/src/generator/rust/inherit.rs | 3 ++- crates/cxx-qt-gen/src/generator/rust/method.rs | 3 +-- .../src/generator/structuring/qobject.rs | 2 +- crates/cxx-qt-gen/src/parser/inherit.rs | 17 ++++++----------- crates/cxx-qt-gen/src/parser/method.rs | 10 +++------- crates/cxx-qt-gen/src/parser/mod.rs | 6 +++++- crates/cxx-qt-gen/src/parser/signals.rs | 8 ++------ 7 files changed, 20 insertions(+), 29 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/inherit.rs b/crates/cxx-qt-gen/src/generator/rust/inherit.rs index 8d7906f99..64ecd1851 100644 --- a/crates/cxx-qt-gen/src/generator/rust/inherit.rs +++ b/crates/cxx-qt-gen/src/generator/rust/inherit.rs @@ -30,6 +30,7 @@ pub fn generate( quote! { #ident: #ty } }) .collect::>(); + let ident = &method.method.sig.ident; let cxx_name_string = &method.wrapper_ident().to_string(); let self_param = if method.mutable { @@ -44,8 +45,8 @@ pub fn generate( if method.safe { std::mem::swap(&mut unsafe_call, &mut unsafe_block); } - let attrs = &method.method.attrs; + let attrs = &method.method.attrs; let doc_comments = &method.docs; syn::parse2(quote_spanned! { diff --git a/crates/cxx-qt-gen/src/generator/rust/method.rs b/crates/cxx-qt-gen/src/generator/rust/method.rs index 4955733d0..8d512dc09 100644 --- a/crates/cxx-qt-gen/src/generator/rust/method.rs +++ b/crates/cxx-qt-gen/src/generator/rust/method.rs @@ -37,10 +37,9 @@ pub fn generate_rust_methods( let return_type = &invokable.method.sig.output; - let mut unsafe_block = None; let mut unsafe_call = Some(quote! { unsafe }); if invokable.safe { - std::mem::swap(&mut unsafe_call, &mut unsafe_block); + std::mem::swap(&mut unsafe_call, &mut None); } let doc_comments = &invokable.docs; diff --git a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs index 467edfaf1..576fcfc7d 100644 --- a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs @@ -21,7 +21,7 @@ pub struct StructuredQObject<'a> { pub signals: Vec<&'a ParsedSignal>, } -fn lookup(invokables: &Vec, id: &Ident) -> Option { +fn lookup(invokables: &[impl Invokable], id: &Ident) -> Option { invokables .iter() .map(|invokable| invokable.name()) diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index 95649dced..d431e9382 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -9,7 +9,7 @@ use crate::parser::{ use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, - syntax::{attribute::attribute_take_path, expr::expr_to_string, safety::Safety}, + syntax::{attribute::attribute_take_path, safety::Safety}, }; use quote::format_ident; use syn::{Attribute, ForeignItemFn, Ident, Result}; @@ -45,25 +45,20 @@ impl ParsedInheritedMethod { let docs = separate_docs(&mut method); let invokable_fields = extract_common_fields(&method, docs)?; - let mut name = - Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; + // This block seems unnecessary but since attrs are passed through on generator/rust/inherit.rs a duplicate attr would occur without it + attribute_take_path(&mut method.attrs, &["cxx_name"]); - // This block seems unnecessary but removing it causes one cxx_name attr in test_outputs to lose the CxxQtInherit suffix - if let Some(attr) = attribute_take_path(&mut method.attrs, &["cxx_name"]) { - name = name.with_cxx_name(expr_to_string(&attr.meta.require_name_value()?.value)?); - } - - Ok(Self::from_invokable_fields(invokable_fields, method, name)) + Ok(Self::from_invokable_fields(invokable_fields, method)) } - fn from_invokable_fields(fields: InvokableFields, method: ForeignItemFn, name: Name) -> Self { + fn from_invokable_fields(fields: InvokableFields, method: ForeignItemFn) -> Self { Self { method, qobject_ident: fields.qobject_ident, mutable: fields.mutable, safe: fields.safe, parameters: fields.parameters, - name, + name: fields.name, docs: fields.docs, } } diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index f378240ea..3b346ae4c 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -70,9 +70,7 @@ impl ParsedMethod { let docs = separate_docs(&mut method); let invokable_fields = extract_common_fields(&method, docs)?; - let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; - - if name.namespace().is_some() { + if invokable_fields.name.namespace().is_some() { return Err(Error::new_spanned( method.sig.ident, "Methods / QInvokables cannot have a namespace attribute", @@ -90,14 +88,13 @@ impl ParsedMethod { ParsedQInvokableSpecifiers::Virtual, ] { if attribute_take_path(&mut method.attrs, specifier.as_str_slice()).is_some() { - specifiers.insert(specifier); + specifiers.insert(specifier); // Should a fn be able to be Override AND Virtual? } } Ok(ParsedMethod::from_invokable_fields( invokable_fields, method, - name, specifiers, is_qinvokable, )) @@ -106,7 +103,6 @@ impl ParsedMethod { fn from_invokable_fields( fields: InvokableFields, method: ForeignItemFn, - name: Name, specifiers: HashSet, is_qinvokable: bool, ) -> Self { @@ -118,7 +114,7 @@ impl ParsedMethod { parameters: fields.parameters, specifiers, is_qinvokable, - name, + name: fields.name, docs: fields.docs, } } diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 5730d7e18..2b5ca9fae 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -44,7 +44,7 @@ fn check_safety(method: &ForeignItemFn, safety: &Safety) -> Result<()> { } pub trait Invokable { - fn name(self: &Self) -> &Name; + fn name(&self) -> &Name; } /// Struct with common fields between Invokable types. @@ -54,6 +54,7 @@ pub struct InvokableFields { mutable: bool, parameters: Vec, safe: bool, + name: Name, docs: Vec, } @@ -69,11 +70,14 @@ pub fn extract_common_fields( let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; let safe = method.sig.unsafety.is_none(); + let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; + Ok(InvokableFields { qobject_ident, mutable, parameters, safe, + name, docs, }) } diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index 1a12c2c27..908634e30 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -89,9 +89,7 @@ impl ParsedSignal { let docs = separate_docs(&mut method); let invokable_fields = extract_common_fields(&method, docs)?; - let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; - - if name.namespace().is_some() { + if invokable_fields.name.namespace().is_some() { return Err(Error::new_spanned( method.sig.ident, "Signals cannot have a namespace attribute", @@ -115,7 +113,6 @@ impl ParsedSignal { Ok(Self::from_invokable_fields( invokable_fields, method, - name, inherit, private, )) @@ -124,7 +121,6 @@ impl ParsedSignal { fn from_invokable_fields( fields: InvokableFields, method: ForeignItemFn, - name: Name, inherit: bool, private: bool, ) -> Self { @@ -134,7 +130,7 @@ impl ParsedSignal { mutable: fields.mutable, safe: fields.safe, parameters: fields.parameters, - name, + name: fields.name, inherit, private, docs: fields.docs, From 47d4c17ca8070fd3dee4f94dac601a01eb734fc6 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Fri, 30 Aug 2024 17:10:17 +0100 Subject: [PATCH 7/8] Remove docs from ParsedMethod --- crates/cxx-qt-gen/src/generator/cpp/method.rs | 1 - crates/cxx-qt-gen/src/generator/naming/method.rs | 1 - crates/cxx-qt-gen/src/generator/rust/method.rs | 8 +------- crates/cxx-qt-gen/src/parser/inherit.rs | 6 ++---- crates/cxx-qt-gen/src/parser/method.rs | 12 +++--------- crates/cxx-qt-gen/src/parser/mod.rs | 13 +++++-------- crates/cxx-qt-gen/src/parser/signals.rs | 6 ++---- 7 files changed, 13 insertions(+), 34 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/cpp/method.rs b/crates/cxx-qt-gen/src/generator/cpp/method.rs index 69a2f173f..3d701b72e 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/method.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/method.rs @@ -328,7 +328,6 @@ mod tests { None, ) .unwrap(), - docs: vec![], }; let invokables = vec![&method]; let qobject_idents = create_qobjectname(); diff --git a/crates/cxx-qt-gen/src/generator/naming/method.rs b/crates/cxx-qt-gen/src/generator/naming/method.rs index 031e0e214..5a47150e7 100644 --- a/crates/cxx-qt-gen/src/generator/naming/method.rs +++ b/crates/cxx-qt-gen/src/generator/naming/method.rs @@ -59,7 +59,6 @@ mod tests { is_qinvokable: true, name: Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None) .unwrap(), - docs: vec![], }; let invokable = QMethodName::try_from(&parsed).unwrap(); diff --git a/crates/cxx-qt-gen/src/generator/rust/method.rs b/crates/cxx-qt-gen/src/generator/rust/method.rs index 8d512dc09..11d07f57a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/method.rs +++ b/crates/cxx-qt-gen/src/generator/rust/method.rs @@ -42,8 +42,6 @@ pub fn generate_rust_methods( std::mem::swap(&mut unsafe_call, &mut None); } - let doc_comments = &invokable.docs; - let fragment = RustFragmentPair { cxx_bridge: vec![quote_spanned! { invokable.method.span() => @@ -52,8 +50,8 @@ pub fn generate_rust_methods( // 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. - #(#doc_comments)* #[cxx_name = #wrapper_ident_cpp] + #[doc(hidden)] // TODO: Add #[namespace] of the QObject #unsafe_call fn #invokable_ident_rust(#parameter_signatures) #return_type; } @@ -108,7 +106,6 @@ mod tests { None, ) .unwrap(), - docs: vec![], }, ParsedMethod { method: method2.clone(), @@ -128,7 +125,6 @@ mod tests { None, ) .unwrap(), - docs: vec![], }, ParsedMethod { method: method3.clone(), @@ -148,7 +144,6 @@ mod tests { None, ) .unwrap(), - docs: vec![], }, ParsedMethod { method: method4.clone(), @@ -168,7 +163,6 @@ mod tests { None, ) .unwrap(), - docs: vec![], }, ]; let qobject_idents = create_qobjectname(); diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index d431e9382..c487ee96b 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -3,9 +3,7 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::parser::{ - check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, -}; +use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, @@ -51,7 +49,7 @@ impl ParsedInheritedMethod { Ok(Self::from_invokable_fields(invokable_fields, method)) } - fn from_invokable_fields(fields: InvokableFields, method: ForeignItemFn) -> Self { + fn from_invokable_fields(fields: MethodFields, method: ForeignItemFn) -> Self { Self { method, qobject_ident: fields.qobject_ident, diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index 3b346ae4c..6e6f17e81 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -9,11 +9,9 @@ use crate::{ syntax::{attribute::attribute_take_path, safety::Safety}, }; use std::collections::HashSet; -use syn::{Attribute, Error, ForeignItemFn, Ident, Result}; +use syn::{Error, ForeignItemFn, Ident, Result}; -use crate::parser::{ - check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, -}; +use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; #[cfg(test)] use quote::format_ident; @@ -53,8 +51,6 @@ pub struct ParsedMethod { pub is_qinvokable: bool, /// The rust and cxx name of the function pub name: Name, - /// All the docs (each line) of the method - pub docs: Vec, } impl Invokable for &ParsedMethod { @@ -101,7 +97,7 @@ impl ParsedMethod { } fn from_invokable_fields( - fields: InvokableFields, + fields: MethodFields, method: ForeignItemFn, specifiers: HashSet, is_qinvokable: bool, @@ -115,7 +111,6 @@ impl ParsedMethod { specifiers, is_qinvokable, name: fields.name, - docs: fields.docs, } } @@ -134,7 +129,6 @@ impl ParsedMethod { is_qinvokable: true, name: Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None) .unwrap(), - docs: vec![], } } diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 2b5ca9fae..d4aa4b4b3 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -49,21 +49,18 @@ pub trait Invokable { /// Struct with common fields between Invokable types. /// These types are ParsedSignal, ParsedMethod and ParsedInheritedMethod -pub struct InvokableFields { +pub struct MethodFields { qobject_ident: Ident, mutable: bool, parameters: Vec, safe: bool, name: Name, - docs: Vec, + docs: Vec, // TODO: Remove this } -/// Function for creating an [InvokableFields] from a method and docs. +/// Function for creating an [MethodFields] from a method and docs. /// These fields are shared by ParsedSignal, ParsedMethod and ParsedInheritedMethod so grouped into common logic. -pub fn extract_common_fields( - method: &ForeignItemFn, - docs: Vec, -) -> Result { +pub fn extract_common_fields(method: &ForeignItemFn, docs: Vec) -> Result { let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; let mutable = mutability.is_some(); @@ -72,7 +69,7 @@ pub fn extract_common_fields( let safe = method.sig.unsafety.is_none(); let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; - Ok(InvokableFields { + Ok(MethodFields { qobject_ident, mutable, parameters, diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index 908634e30..6643e2147 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -10,9 +10,7 @@ use crate::{ }; use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result, Visibility}; -use crate::parser::{ - check_safety, extract_common_fields, separate_docs, Invokable, InvokableFields, -}; +use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; #[cfg(test)] use quote::format_ident; @@ -119,7 +117,7 @@ impl ParsedSignal { } fn from_invokable_fields( - fields: InvokableFields, + fields: MethodFields, method: ForeignItemFn, inherit: bool, private: bool, From f726eb77980405a65a9ddc65589a10d9f200a922 Mon Sep 17 00:00:00 2001 From: Ben Ford Date: Mon, 2 Sep 2024 10:54:32 +0100 Subject: [PATCH 8/8] Respond to comments - Moved MethodFields and its renamed method to method.rs - Updated the expected outputs - Refactor the lookup method to be generic, and remove the superfluous trait --- .../cxx-qt-gen/src/generator/rust/method.rs | 4 ++ .../src/generator/structuring/qobject.rs | 12 ++--- crates/cxx-qt-gen/src/parser/inherit.rs | 11 ++--- crates/cxx-qt-gen/src/parser/method.rs | 45 +++++++++++++++---- crates/cxx-qt-gen/src/parser/mod.rs | 39 ---------------- crates/cxx-qt-gen/src/parser/signals.rs | 11 ++--- crates/cxx-qt-gen/test_outputs/inheritance.rs | 2 + crates/cxx-qt-gen/test_outputs/invokables.rs | 11 +++++ .../test_outputs/passthrough_and_naming.rs | 2 + crates/cxx-qt-gen/test_outputs/properties.rs | 3 ++ crates/cxx-qt-gen/test_outputs/qenum.rs | 1 + crates/cxx-qt-gen/test_outputs/signals.rs | 1 + 12 files changed, 72 insertions(+), 70 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/method.rs b/crates/cxx-qt-gen/src/generator/rust/method.rs index 11d07f57a..a076e519c 100644 --- a/crates/cxx-qt-gen/src/generator/rust/method.rs +++ b/crates/cxx-qt-gen/src/generator/rust/method.rs @@ -179,6 +179,7 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "voidInvokableWrapper"] + #[doc(hidden)] fn void_invokable(self: &MyObject); } }, @@ -190,6 +191,7 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "trivialInvokableWrapper"] + #[doc(hidden)] fn trivial_invokable(self: &MyObject, param: i32) -> i32; } }, @@ -201,6 +203,7 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "opaqueInvokableWrapper"] + #[doc(hidden)] fn opaque_invokable(self: Pin<&mut MyObject>, param: &QColor) -> UniquePtr; } }, @@ -212,6 +215,7 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "unsafeInvokableWrapper"] + #[doc(hidden)] unsafe fn unsafe_invokable(self:&MyObject, param: *mut T) -> *mut T; } }, diff --git a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs index 576fcfc7d..e2abcfe50 100644 --- a/crates/cxx-qt-gen/src/generator/structuring/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/structuring/qobject.rs @@ -7,7 +7,7 @@ use crate::naming::Name; use crate::parser::inherit::ParsedInheritedMethod; use crate::parser::method::ParsedMethod; use crate::parser::signals::ParsedSignal; -use crate::parser::{qenum::ParsedQEnum, qobject::ParsedQObject, Invokable}; +use crate::parser::{qenum::ParsedQEnum, qobject::ParsedQObject}; use proc_macro2::Ident; use syn::{Error, Result}; @@ -21,10 +21,10 @@ pub struct StructuredQObject<'a> { pub signals: Vec<&'a ParsedSignal>, } -fn lookup(invokables: &[impl Invokable], id: &Ident) -> Option { +fn lookup(invokables: &[T], id: &Ident, name_getter: impl Fn(&T) -> &Name) -> Option { invokables .iter() - .map(|invokable| invokable.name()) + .map(name_getter) .find(|name| name.rust_unqualified() == id) .cloned() } @@ -47,14 +47,14 @@ impl<'a> StructuredQObject<'a> { /// Returns the name of the method with the provided Rust ident if it exists, or an error pub fn method_lookup(&self, id: &Ident) -> Result { - lookup(&self.methods, id) - .or_else(|| lookup(&self.inherited_methods, id)) // fallback to searching inherited methods + lookup(&self.methods, id, |method| &method.name) + .or_else(|| lookup(&self.inherited_methods, id, |inherited| &inherited.name)) // fallback to searching inherited methods .ok_or_else(|| Error::new_spanned(id, format!("Method with name '{id}' not found!"))) } /// Returns the name of the signal with the provided Rust ident if it exists, or an error pub fn signal_lookup(&self, id: &Ident) -> Result { - lookup(&self.signals, id) + lookup(&self.signals, id, |signal| &signal.name) .ok_or_else(|| Error::new_spanned(id, format!("Signal with name '{id}' not found!"))) } diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index c487ee96b..989199d07 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -3,7 +3,8 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; +use crate::parser::method::MethodFields; +use crate::parser::{check_safety, separate_docs}; use crate::{ naming::Name, parser::parameter::ParsedFunctionParameter, @@ -30,18 +31,12 @@ pub struct ParsedInheritedMethod { pub docs: Vec, } -impl Invokable for &ParsedInheritedMethod { - fn name(&self) -> &Name { - &self.name - } -} - impl ParsedInheritedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { check_safety(&method, &safety)?; let docs = separate_docs(&mut method); - let invokable_fields = extract_common_fields(&method, docs)?; + let invokable_fields = MethodFields::parse(&method, docs)?; // This block seems unnecessary but since attrs are passed through on generator/rust/inherit.rs a duplicate attr would occur without it attribute_take_path(&mut method.attrs, &["cxx_name"]); diff --git a/crates/cxx-qt-gen/src/parser/method.rs b/crates/cxx-qt-gen/src/parser/method.rs index 6e6f17e81..29a84adea 100644 --- a/crates/cxx-qt-gen/src/parser/method.rs +++ b/crates/cxx-qt-gen/src/parser/method.rs @@ -9,9 +9,10 @@ use crate::{ syntax::{attribute::attribute_take_path, safety::Safety}, }; use std::collections::HashSet; -use syn::{Error, ForeignItemFn, Ident, Result}; +use syn::{Attribute, Error, ForeignItemFn, Ident, Result}; -use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; +use crate::parser::{check_safety, separate_docs}; +use crate::syntax::{foreignmod, types}; #[cfg(test)] use quote::format_ident; @@ -53,18 +54,12 @@ pub struct ParsedMethod { pub name: Name, } -impl Invokable for &ParsedMethod { - fn name(&self) -> &Name { - &self.name - } -} - impl ParsedMethod { pub fn parse(mut method: ForeignItemFn, safety: Safety) -> Result { check_safety(&method, &safety)?; let docs = separate_docs(&mut method); - let invokable_fields = extract_common_fields(&method, docs)?; + let invokable_fields = MethodFields::parse(&method, docs)?; if invokable_fields.name.namespace().is_some() { return Err(Error::new_spanned( @@ -143,3 +138,35 @@ impl ParsedMethod { } } } + +/// Struct with common fields between Invokable types. +/// These types are ParsedSignal, ParsedMethod and ParsedInheritedMethod +pub struct MethodFields { + pub qobject_ident: Ident, + pub mutable: bool, + pub parameters: Vec, + pub safe: bool, + pub name: Name, + pub docs: Vec, // TODO: Remove this +} + +impl MethodFields { + pub fn parse(method: &ForeignItemFn, docs: Vec) -> Result { + let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; + let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; + let mutable = mutability.is_some(); + + let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; + let safe = method.sig.unsafety.is_none(); + let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; + + Ok(MethodFields { + qobject_ident, + mutable, + parameters, + safe, + name, + docs, + }) + } +} diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index d4aa4b4b3..c64e89a76 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -15,10 +15,7 @@ pub mod qnamespace; pub mod qobject; pub mod signals; -use crate::naming::Name; -use crate::parser::parameter::ParsedFunctionParameter; use crate::syntax::safety::Safety; -use crate::syntax::{foreignmod, types}; use crate::{ // Used for error handling when resolving the namespace of the qenum. naming::TypeNames, @@ -43,42 +40,6 @@ fn check_safety(method: &ForeignItemFn, safety: &Safety) -> Result<()> { } } -pub trait Invokable { - fn name(&self) -> &Name; -} - -/// Struct with common fields between Invokable types. -/// These types are ParsedSignal, ParsedMethod and ParsedInheritedMethod -pub struct MethodFields { - qobject_ident: Ident, - mutable: bool, - parameters: Vec, - safe: bool, - name: Name, - docs: Vec, // TODO: Remove this -} - -/// Function for creating an [MethodFields] from a method and docs. -/// These fields are shared by ParsedSignal, ParsedMethod and ParsedInheritedMethod so grouped into common logic. -pub fn extract_common_fields(method: &ForeignItemFn, docs: Vec) -> Result { - let self_receiver = foreignmod::self_type_from_foreign_fn(&method.sig)?; - let (qobject_ident, mutability) = types::extract_qobject_ident(&self_receiver.ty)?; - let mutable = mutability.is_some(); - - let parameters = ParsedFunctionParameter::parse_all_ignoring_receiver(&method.sig)?; - let safe = method.sig.unsafety.is_none(); - let name = Name::from_rust_ident_and_attrs(&method.sig.ident, &method.attrs, None, None)?; - - Ok(MethodFields { - qobject_ident, - mutable, - parameters, - safe, - name, - docs, - }) -} - /// Iterate the attributes of the method to extract Doc attributes (doc comments are parsed as this) /// /// Note: This modifies the method by removing those doc attributes diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index 6643e2147..cd8f300a4 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -10,7 +10,8 @@ use crate::{ }; use syn::{spanned::Spanned, Attribute, Error, ForeignItemFn, Ident, Result, Visibility}; -use crate::parser::{check_safety, extract_common_fields, separate_docs, Invokable, MethodFields}; +use crate::parser::method::MethodFields; +use crate::parser::{check_safety, separate_docs}; #[cfg(test)] use quote::format_ident; @@ -37,12 +38,6 @@ pub struct ParsedSignal { pub docs: Vec, } -impl Invokable for &ParsedSignal { - fn name(&self) -> &Name { - &self.name - } -} - impl ParsedSignal { /// Builds a signal from a given property method pub fn from_property_method( @@ -85,7 +80,7 @@ impl ParsedSignal { check_safety(&method, &safety)?; let docs = separate_docs(&mut method); - let invokable_fields = extract_common_fields(&method, docs)?; + let invokable_fields = MethodFields::parse(&method, docs)?; if invokable_fields.name.namespace().is_some() { return Err(Error::new_spanned( diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index f213af3e7..bb0bb61f4 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -35,10 +35,12 @@ mod inheritance { } extern "Rust" { #[cxx_name = "dataWrapper"] + #[doc(hidden)] fn data(self: &MyObject, _index: &QModelIndex, _role: i32) -> QVariant; } extern "Rust" { #[cxx_name = "hasChildrenWrapper"] + #[doc(hidden)] fn has_children(self: &MyObject, _parent: &QModelIndex) -> bool; } unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index eb1dba81c..16a867ff1 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -42,46 +42,57 @@ mod ffi { } extern "Rust" { #[cxx_name = "cppMethodWrapper"] + #[doc(hidden)] fn cpp_method(self: &MyObject); } extern "Rust" { #[cxx_name = "invokableWrapper"] + #[doc(hidden)] fn invokable(self: &MyObject); } extern "Rust" { #[cxx_name = "invokableMutableWrapper"] + #[doc(hidden)] fn invokable_mutable(self: Pin<&mut MyObject>); } extern "Rust" { #[cxx_name = "invokableParametersWrapper"] + #[doc(hidden)] fn invokable_parameters(self: &MyObject, opaque: &QColor, trivial: &QPoint, primitive: i32); } extern "Rust" { #[cxx_name = "invokableReturnOpaqueWrapper"] + #[doc(hidden)] fn invokable_return_opaque(self: Pin<&mut MyObject>) -> UniquePtr; } extern "Rust" { #[cxx_name = "invokableReturnTrivialWrapper"] + #[doc(hidden)] fn invokable_return_trivial(self: Pin<&mut MyObject>) -> QPoint; } extern "Rust" { #[cxx_name = "invokableFinalWrapper"] + #[doc(hidden)] fn invokable_final(self: &MyObject); } extern "Rust" { #[cxx_name = "invokableOverrideWrapper"] + #[doc(hidden)] fn invokable_override(self: &MyObject); } extern "Rust" { #[cxx_name = "invokableVirtualWrapper"] + #[doc(hidden)] fn invokable_virtual(self: &MyObject); } extern "Rust" { #[cxx_name = "invokableResultTupleWrapper"] + #[doc(hidden)] fn invokable_result_tuple(self: &MyObject) -> Result<()>; } extern "Rust" { #[cxx_name = "invokableResultTypeWrapper"] + #[doc(hidden)] fn invokable_result_type(self: &MyObject) -> Result; } unsafe extern "C++" { 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 c160c1eb3..531242788 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -125,6 +125,7 @@ pub mod ffi { } extern "Rust" { #[cxx_name = "invokableNameWrapper"] + #[doc(hidden)] fn invokable_name(self: Pin<&mut MyObject>); } unsafe extern "C++" { @@ -257,6 +258,7 @@ pub mod ffi { } extern "Rust" { #[cxx_name = "invokableNameWrapper"] + #[doc(hidden)] fn invokable_name(self: Pin<&mut SecondObject>); } unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 67b5303e3..c43370cc5 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -188,14 +188,17 @@ mod ffi { } extern "Rust" { #[cxx_name = "myGetterWrapper"] + #[doc(hidden)] fn my_getter(self: &MyObject) -> i32; } extern "Rust" { #[cxx_name = "MyCustomSetterWrapper"] + #[doc(hidden)] fn my_setter(self: Pin<&mut MyObject>, value: i32); } extern "Rust" { #[cxx_name = "myResetFnWrapper"] + #[doc(hidden)] fn myResetFn(self: Pin<&mut MyObject>); } unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_outputs/qenum.rs b/crates/cxx-qt-gen/test_outputs/qenum.rs index 75e807843..da72a117d 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.rs +++ b/crates/cxx-qt-gen/test_outputs/qenum.rs @@ -79,6 +79,7 @@ mod ffi { } extern "Rust" { #[cxx_name = "myInvokableWrapper"] + #[doc(hidden)] fn my_invokable(self: &MyObject, qenum: MyEnum, other_qenum: MyOtherEnum); } extern "Rust" { diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index f92678d9a..44def4728 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -36,6 +36,7 @@ mod ffi { } extern "Rust" { #[cxx_name = "invokableWrapper"] + #[doc(hidden)] fn invokable(self: Pin<&mut MyObject>); } unsafe extern "C++" {