Skip to content
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

cxx-qt-gen: generate docs for public generated items #518

Merged
merged 7 commits into from
May 17, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Allow associated constants, types and macro invocations within `impl qobject::T` blocks
- Ensure that generated Rust code works when `#![deny(missing_docs)]` is enabled

### Changed

Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,18 +194,22 @@ endif()
# from the main build.
set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/${BUILD_DIR}/cargo/build")

# Add CMake tests for `cargo test/clippy/fmt`.
# Add CMake tests for `cargo test/clippy/fmt/doc`.
add_test(NAME cargo_tests COMMAND cargo test --all-targets --target-dir
${CARGO_TARGET_DIR})
add_test(NAME cargo_doc_tests COMMAND cargo test --doc --target-dir
${CARGO_TARGET_DIR})
add_test(NAME cargo_doc COMMAND cargo doc --workspace --target-dir ${CARGO_TARGET_DIR})
add_test(NAME cargo_clippy COMMAND cargo clippy --all-targets --target-dir
${CARGO_TARGET_DIR} -- -D warnings)
add_test(NAME cargo_fmt COMMAND cargo fmt --all --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

set_tests_properties(cargo_tests cargo_doc_tests cargo_clippy cargo_fmt PROPERTIES
ENVIRONMENT_MODIFICATION "${CARGO_ENV}"
)
set_tests_properties(cargo_doc PROPERTIES
ENVIRONMENT_MODIFICATION "${CARGO_ENV};RUSTDOCFLAGS=set:--deny=warnings"
)

# Ensure test inputs and outputs are formatted
file(GLOB CXX_QT_GEN_TEST_INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/crates/cxx-qt-gen/test_inputs/*.rs)
Expand Down
6 changes: 3 additions & 3 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,12 @@ fn generate_cxxqt_cpp_files(
Ok(generated_file_paths)
}

/// Run cxx-qt's C++ code generator on Rust modules marked with the [cxx_qt::bridge] macro, compile
/// the code, and link to Qt. This is the complement of the [cxx_qt::bridge] macro, which the Rust
/// Run cxx-qt's C++ code generator on Rust modules marked with the `cxx_qt::bridge` macro, compile
/// the code, and link to Qt. This is the complement of the `cxx_qt::bridge` macro, which the Rust
/// compiler uses to generate the corresponding Rust code. No dependencies besides Qt, a C++17 compiler,
/// and Rust toolchain are required.
///
/// For example, if your [cxx_qt::bridge] module is in a file called `src/lib.rs` within your crate,
/// For example, if your `cxx_qt::bridge` module is in a file called `src/lib.rs` within your crate,
/// put this in your [build.rs](https://doc.rust-lang.org/cargo/reference/build-scripts.html):
///
/// ```no_run
Expand Down
21 changes: 17 additions & 4 deletions crates/cxx-qt-gen/src/generator/rust/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub fn generate(
.collect::<Vec<TokenStream>>();
let ident = &method.method.sig.ident;
let cxx_name_string = &method.wrapper_ident().to_string();
let ident_cpp_str = method.ident.cpp.to_string();
let self_param = if method.mutable {
quote! { self: Pin<&mut #qobject_name> }
} else {
Expand All @@ -46,7 +47,10 @@ pub fn generate(
}
syn::parse2(quote! {
#unsafe_block extern "C++" {
#[cxx_name=#cxx_name_string]
#[doc = "CXX-Qt generated method which calls the C++ method"]
#[doc = #ident_cpp_str]
#[doc = "on the base class"]
#[cxx_name = #cxx_name_string]
#unsafe_call fn #ident(#self_param, #(#parameters),*) #return_type;
}
})
Expand Down Expand Up @@ -91,7 +95,10 @@ mod tests {
&generated.cxx_mod_contents[0],
quote! {
unsafe extern "C++" {
#[cxx_name="testCxxQtInherit"]
#[doc = "CXX-Qt generated method which calls the C++ method"]
#[doc = "test"]
#[doc = "on the base class"]
#[cxx_name = "testCxxQtInherit"]
fn test(self: Pin<&mut MyObjectQt>, a: B, b: C);
}
},
Expand All @@ -115,7 +122,10 @@ mod tests {
&generated.cxx_mod_contents[0],
quote! {
unsafe extern "C++" {
#[cxx_name="testCxxQtInherit"]
#[doc = "CXX-Qt generated method which calls the C++ method"]
#[doc = "test"]
#[doc = "on the base class"]
#[cxx_name = "testCxxQtInherit"]
fn test(self: &MyObjectQt, a: B, b: C);
}
},
Expand All @@ -140,7 +150,10 @@ mod tests {
// TODO: Maybe remove the trailing comma after self?
quote! {
extern "C++" {
#[cxx_name="testCxxQtInherit"]
#[doc = "CXX-Qt generated method which calls the C++ method"]
#[doc = "test"]
#[doc = "on the base class"]
#[cxx_name = "testCxxQtInherit"]
unsafe fn test(self: &MyObjectQt,);
}
},
Expand Down
5 changes: 5 additions & 0 deletions crates/cxx-qt-gen/src/generator/rust/invokable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub fn generate_rust_invokables(
// TODO: not all methods have a wrapper
quote! {
impl #rust_struct_name_rust {
#[doc(hidden)]
pub #has_unsafe fn #wrapper_ident_rust(#parameter_signatures) #return_type {
#has_return cpp.#invokable_ident_rust(#(#parameter_names),*);
}
Expand Down Expand Up @@ -194,6 +195,7 @@ mod tests {
&generated.cxx_qt_mod_contents[0],
quote! {
impl MyObject {
#[doc(hidden)]
pub fn void_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt) {
cpp.void_invokable();
}
Expand Down Expand Up @@ -223,6 +225,7 @@ mod tests {
&generated.cxx_qt_mod_contents[2],
quote! {
impl MyObject {
#[doc(hidden)]
pub fn trivial_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: i32) -> i32 {
return cpp.trivial_invokable(param);
}
Expand Down Expand Up @@ -252,6 +255,7 @@ mod tests {
&generated.cxx_qt_mod_contents[4],
quote! {
impl MyObject {
#[doc(hidden)]
pub fn opaque_invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, param: &QColor) -> UniquePtr<QColor> {
return cpp.opaque_invokable(param);
}
Expand Down Expand Up @@ -281,6 +285,7 @@ mod tests {
&generated.cxx_qt_mod_contents[6],
quote! {
impl MyObject {
#[doc(hidden)]
pub unsafe fn unsafe_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: *mut T) -> *mut T {
return cpp.unsafe_invokable(param);
}
Expand Down
12 changes: 12 additions & 0 deletions crates/cxx-qt-gen/src/generator/rust/property/getter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub fn generate(
let getter_rust = &idents.getter.rust;
let getter_mutable_rust = &idents.getter_mutable.rust;
let ident = &idents.name.rust;
let ident_str = ident.to_string();
let notify_ident_str = idents.notify.rust.to_string();

RustFragmentPair {
cxx_bridge: vec![quote! {
Expand All @@ -32,20 +34,30 @@ pub fn generate(
implementation: vec![
quote! {
impl #rust_struct_name_rust {
#[doc(hidden)]
pub fn #getter_rust<'a>(&'a self, cpp: &'a #cpp_class_name_rust) -> &'a #ty {
cpp.#getter_rust()
}
}
},
quote! {
impl #cpp_class_name_rust {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = #ident_str]
pub fn #getter_rust(&self) -> &#ty {
&self.rust().#ident
}
}
},
quote! {
impl #cpp_class_name_rust {
#[doc = "unsafe getter for the Q_PROPERTY "]
#[doc = #ident_str]
#[doc = "\n"]
#[doc = "This allows for modifying the Q_PROPERTY without calling the property changed Q_SIGNAL"]
ahayzen-kdab marked this conversation as resolved.
Show resolved Hide resolved
#[doc = "\n"]
#[doc = "After modifying the property, make sure to call the corresponding changed signal: "]
#[doc = #notify_ident_str]
pub unsafe fn #getter_mutable_rust<'a>(mut self: Pin<&'a mut Self>) -> &'a mut #ty {
&mut self.rust_mut().get_unchecked_mut().#ident
}
Expand Down
57 changes: 57 additions & 0 deletions crates/cxx-qt-gen/src/generator/rust/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ mod tests {
generated.cxx_qt_mod_contents[0],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn trivial_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a i32 {
cpp.trivial_property()
}
Expand All @@ -120,6 +121,8 @@ mod tests {
generated.cxx_qt_mod_contents[1],
parse_quote! {
impl MyObjectQt {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = "trivial_property"]
pub fn trivial_property(&self) -> &i32 {
&self.rust().trivial_property
}
Expand All @@ -130,6 +133,13 @@ mod tests {
generated.cxx_qt_mod_contents[2],
parse_quote! {
impl MyObjectQt {
#[doc = "unsafe getter for the Q_PROPERTY "]
#[doc = "trivial_property"]
#[doc = "\n"]
#[doc = "This allows for modifying the Q_PROPERTY without calling the property changed Q_SIGNAL"]
#[doc = "\n"]
#[doc = "After modifying the property, make sure to call the corresponding changed signal: "]
#[doc = "trivial_property_changed"]
pub unsafe fn trivial_property_mut<'a>(mut self: Pin<&'a mut Self>) -> &'a mut i32 {
&mut self.rust_mut().get_unchecked_mut().trivial_property
}
Expand All @@ -151,6 +161,7 @@ mod tests {
generated.cxx_qt_mod_contents[3],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn set_trivial_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: i32) {
cpp.set_trivial_property(value);
}
Expand All @@ -161,6 +172,8 @@ mod tests {
generated.cxx_qt_mod_contents[4],
parse_quote! {
impl MyObjectQt {
#[doc = "Setter for the Q_PROPERTY "]
#[doc = "trivial_property"]
pub fn set_trivial_property(mut self: Pin<&mut Self>, value: i32) {
if self.rust().trivial_property == value {
return;
Expand All @@ -179,6 +192,12 @@ mod tests {
generated.cxx_mod_contents[2],
parse_quote! {
unsafe extern "C++" {
#[doc = "Notify signal for the Q_PROPERTY"]
#[doc = "trivial_property"]
#[doc = "\n"]
#[doc = "This can be used to manually notify a change when the unsafe mutable getter,"]
#[doc = "trivial_property_mut"]
#[doc = ", is used."]
#[rust_name = "trivial_property_changed"]
fn trivialPropertyChanged(self: Pin<&mut MyObjectQt>);
}
Expand All @@ -201,6 +220,7 @@ mod tests {
generated.cxx_qt_mod_contents[5],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn opaque_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a UniquePtr<QColor> {
cpp.opaque_property()
}
Expand All @@ -211,6 +231,8 @@ mod tests {
generated.cxx_qt_mod_contents[6],
parse_quote! {
impl MyObjectQt {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = "opaque_property"]
pub fn opaque_property(&self) -> &UniquePtr<QColor> {
&self.rust().opaque_property
}
Expand All @@ -221,6 +243,13 @@ mod tests {
generated.cxx_qt_mod_contents[7],
parse_quote! {
impl MyObjectQt {
#[doc = "unsafe getter for the Q_PROPERTY "]
#[doc = "opaque_property"]
#[doc = "\n"]
#[doc = "This allows for modifying the Q_PROPERTY without calling the property changed Q_SIGNAL"]
#[doc = "\n"]
#[doc = "After modifying the property, make sure to call the corresponding changed signal: "]
#[doc = "opaque_property_changed"]
pub unsafe fn opaque_property_mut<'a>(mut self: Pin<&'a mut Self>) -> &'a mut UniquePtr<QColor> {
&mut self.rust_mut().get_unchecked_mut().opaque_property
}
Expand All @@ -242,6 +271,7 @@ mod tests {
generated.cxx_qt_mod_contents[8],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn set_opaque_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: UniquePtr<QColor>) {
cpp.set_opaque_property(value);
}
Expand All @@ -252,6 +282,8 @@ mod tests {
generated.cxx_qt_mod_contents[9],
parse_quote! {
impl MyObjectQt {
#[doc = "Setter for the Q_PROPERTY "]
#[doc = "opaque_property"]
pub fn set_opaque_property(mut self: Pin<&mut Self>, value: UniquePtr<QColor>) {
if self.rust().opaque_property == value {
return;
Expand All @@ -270,6 +302,12 @@ mod tests {
generated.cxx_mod_contents[5],
parse_quote! {
unsafe extern "C++" {
#[doc = "Notify signal for the Q_PROPERTY"]
#[doc = "opaque_property"]
#[doc = "\n"]
#[doc = "This can be used to manually notify a change when the unsafe mutable getter,"]
#[doc = "opaque_property_mut"]
#[doc = ", is used."]
#[rust_name = "opaque_property_changed"]
fn opaquePropertyChanged(self: Pin<&mut MyObjectQt>);
}
Expand All @@ -292,6 +330,7 @@ mod tests {
generated.cxx_qt_mod_contents[10],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn unsafe_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a *mut T {
cpp.unsafe_property()
}
Expand All @@ -302,6 +341,8 @@ mod tests {
generated.cxx_qt_mod_contents[11],
parse_quote! {
impl MyObjectQt {
#[doc = "Getter for the Q_PROPERTY "]
#[doc = "unsafe_property"]
pub fn unsafe_property(&self) -> &*mut T {
&self.rust().unsafe_property
}
Expand All @@ -312,6 +353,13 @@ mod tests {
generated.cxx_qt_mod_contents[12],
parse_quote! {
impl MyObjectQt {
#[doc = "unsafe getter for the Q_PROPERTY "]
#[doc = "unsafe_property"]
#[doc = "\n"]
#[doc = "This allows for modifying the Q_PROPERTY without calling the property changed Q_SIGNAL"]
#[doc = "\n"]
#[doc = "After modifying the property, make sure to call the corresponding changed signal: "]
#[doc = "unsafe_property_changed"]
pub unsafe fn unsafe_property_mut<'a>(mut self: Pin<&'a mut Self>) -> &'a mut *mut T {
&mut self.rust_mut().get_unchecked_mut().unsafe_property
}
Expand All @@ -333,6 +381,7 @@ mod tests {
generated.cxx_qt_mod_contents[13],
parse_quote! {
impl MyObject {
#[doc(hidden)]
pub fn set_unsafe_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: *mut T) {
cpp.set_unsafe_property(value);
}
Expand All @@ -343,6 +392,8 @@ mod tests {
generated.cxx_qt_mod_contents[14],
parse_quote! {
impl MyObjectQt {
#[doc = "Setter for the Q_PROPERTY "]
#[doc = "unsafe_property"]
pub fn set_unsafe_property(mut self: Pin<&mut Self>, value: *mut T) {
if self.rust().unsafe_property == value {
return;
Expand All @@ -361,6 +412,12 @@ mod tests {
generated.cxx_mod_contents[8],
parse_quote! {
unsafe extern "C++" {
#[doc = "Notify signal for the Q_PROPERTY"]
#[doc = "unsafe_property"]
#[doc = "\n"]
#[doc = "This can be used to manually notify a change when the unsafe mutable getter,"]
#[doc = "unsafe_property_mut"]
#[doc = ", is used."]
#[rust_name = "unsafe_property_changed"]
fn unsafePropertyChanged(self: Pin<&mut MyObjectQt>);
}
Expand Down
4 changes: 4 additions & 0 deletions crates/cxx-qt-gen/src/generator/rust/property/setter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn generate(
let setter_cpp = idents.setter.cpp.to_string();
let setter_rust = &idents.setter.rust;
let ident = &idents.name.rust;
let ident_str = ident.to_string();
let notify_ident = &idents.notify.rust;

// Determine if unsafe is required due to an unsafe type
Expand All @@ -39,13 +40,16 @@ pub fn generate(
implementation: vec![
quote! {
impl #rust_struct_name_rust {
#[doc(hidden)]
pub fn #setter_rust(&mut self, cpp: Pin<&mut #cpp_class_name_rust>, value: #ty) {
cpp.#setter_rust(value);
}
}
},
quote! {
impl #cpp_class_name_rust {
#[doc = "Setter for the Q_PROPERTY "]
#[doc = #ident_str]
pub fn #setter_rust(mut self: Pin<&mut Self>, value: #ty) {
if self.rust().#ident == value {
// don't want to set the value again and reemit the signal,
Expand Down
Loading