Skip to content

Commit

Permalink
cxx-qt-gen: have an explicit error for non public qobjects
Browse files Browse the repository at this point in the history
Before this patch if you didn't mark a qobject struct as public
the following error would occur.

```
[build] error[E0432]: unresolved import `super`
[build]   --> examples/qml_minimal/rust/src/cxxqt_object.rs:24:12
[build]    |
[build] 24 |     struct MyObject {
[build]    |            ^^^^^^^^ no `MyObject` in `cxxqt_object`
[build]    |
[build] help: consider importing this type alias instead
[build]    |
[build] 24 |     struct crate::cxxqt_object::qobject::MyObject;
[build]    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

After this patch the error is explicit.

```
[build] error: qobject marked structs must be public
[build]   --> examples/qml_minimal/rust/src/cxxqt_object.rs:24:5
[build]    |
[build] 24 |     struct MyObject {
[build]    |     ^^^^^^
```

Closes KDAB#457
  • Loading branch information
ahayzen-kdab committed Mar 2, 2023
1 parent 66a5b61 commit fbe4d03
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 43 deletions.
6 changes: 3 additions & 3 deletions crates/cxx-qt-gen/src/generator/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -76,7 +76,7 @@ mod tests {
#[cxx_qt::bridge(cxx_file_stem = "my_object")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -93,7 +93,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand Down
10 changes: 5 additions & 5 deletions crates/cxx-qt-gen/src/generator/cpp/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -156,7 +156,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject(base = "QStringListModel")]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -177,7 +177,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_name = "MyQmlElement")]
struct MyNamedObject;
pub struct MyNamedObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -201,7 +201,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -226,7 +226,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_uncreatable)]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand Down
8 changes: 4 additions & 4 deletions crates/cxx-qt-gen/src/generator/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -98,7 +98,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -119,7 +119,7 @@ mod tests {
use std::collections::HashMap;

#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -138,7 +138,7 @@ mod tests {
#[cxx_qt::bridge(cxx_file_stem = "my_object")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand Down
6 changes: 3 additions & 3 deletions crates/cxx-qt-gen/src/generator/rust/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -218,7 +218,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand All @@ -241,7 +241,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)]
struct MyObject;
pub struct MyObject;
}
});
let parser = Parser::from(module).unwrap();
Expand Down
20 changes: 10 additions & 10 deletions crates/cxx-qt-gen/src/parser/cxxqtdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ mod tests {
mod module {
struct Other;
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
}
});
let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1);
Expand All @@ -345,11 +345,11 @@ mod tests {

let module: ItemMod = tokens_to_syn(quote! {
mod module {
struct Other;
pub struct Other;
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
#[cxx_qt::qobject]
struct SecondObject;
pub struct SecondObject;
}
});
let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1);
Expand All @@ -370,11 +370,11 @@ mod tests {

let module: ItemMod = tokens_to_syn(quote! {
mod module {
struct Other;
pub struct Other;
#[cxx_qt::qobject(namespace = "qobject_namespace")]
struct MyObject;
pub struct MyObject;
#[cxx_qt::qobject]
struct SecondObject;
pub struct SecondObject;
}
});
cxx_qt_data
Expand Down Expand Up @@ -405,8 +405,8 @@ mod tests {

let module: ItemMod = tokens_to_syn(quote! {
mod module {
struct Other;
struct MyObject;
pub struct Other;
pub struct MyObject;
}
});
let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1);
Expand Down Expand Up @@ -477,7 +477,7 @@ mod tests {

let item: Item = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
});
let result = cxx_qt_data.parse_cxx_qt_item(item).unwrap();
assert!(result.is_none());
Expand Down
6 changes: 3 additions & 3 deletions crates/cxx-qt-gen/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ mod tests {
#[cxx_qt::bridge(namespace = "cxx_qt")]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;

#[cxx_qt::qsignals(MyObject)]
enum MySignals {
Expand All @@ -188,7 +188,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;

#[cxx_qt::qsignals(MyObject)]
enum MySignals {
Expand Down Expand Up @@ -217,7 +217,7 @@ mod tests {
#[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;

#[cxx_qt::qsignals(UnknownObj)]
enum MySignals {
Expand Down
39 changes: 24 additions & 15 deletions crates/cxx-qt-gen/src/parser/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::syntax::{
};
use syn::{
spanned::Spanned, Error, Fields, Ident, ImplItem, ImplItemMethod, Item, ItemStruct, LitStr,
Result,
Result, Visibility,
};

/// Metadata for registering QML element
Expand Down Expand Up @@ -94,6 +94,15 @@ impl ParsedQObject {
// and remove the #[qproperty] attribute
let (properties, fields) = Self::parse_struct_fields(&mut qobject_struct.fields)?;

// Ensure that the QObject is marked as pub otherwise the error is non obvious
// https://github.com/KDAB/cxx-qt/issues/457
if !matches!(qobject_struct.vis, Visibility::Public(..)) {
return Err(Error::new(
qobject_struct.span(),
"qobject marked structs must be public",
));
}

Ok(Self {
base_class,
qobject_struct,
Expand Down Expand Up @@ -259,7 +268,7 @@ pub mod tests {
pub fn create_parsed_qobject() -> ParsedQObject {
let qobject_struct: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
});
ParsedQObject::from_struct(&qobject_struct, 0).unwrap()
}
Expand All @@ -268,7 +277,7 @@ pub mod tests {
fn test_from_struct_no_base_class() {
let qobject_struct: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct MyObject;
pub struct MyObject;
});

let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap();
Expand All @@ -280,7 +289,7 @@ pub mod tests {
fn test_from_struct_base_class() {
let qobject_struct: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(base = "QStringListModel")]
struct MyObject;
pub struct MyObject;
});

let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap();
Expand All @@ -291,7 +300,7 @@ pub mod tests {
fn test_from_struct_properties_and_fields() {
let qobject_struct: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct MyObject {
pub struct MyObject {
#[qproperty]
int_property: i32,

Expand All @@ -311,7 +320,7 @@ pub mod tests {
fn test_from_struct_fields() {
let qobject_struct: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct MyObject {
pub struct MyObject {
field: i32,
}
});
Expand Down Expand Up @@ -388,7 +397,7 @@ pub mod tests {
fn test_parse_struct_fields_valid() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct T {
pub struct T {
#[qproperty]
f64_property: f64,

Expand Down Expand Up @@ -423,7 +432,7 @@ pub mod tests {
fn test_parse_struct_fields_invalid() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject]
struct T(f64);
pub struct T(f64);
});
assert!(ParsedQObject::from_struct(&item, 0).is_err());
}
Expand All @@ -432,7 +441,7 @@ pub mod tests {
fn test_qml_metadata() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1.0")]
struct MyObject;
pub struct MyObject;
});
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
assert_eq!(
Expand All @@ -452,7 +461,7 @@ pub mod tests {
fn test_qml_metadata_named() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_name = "MyQmlElement")]
struct MyNamedObject;
pub struct MyNamedObject;
});
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
assert_eq!(
Expand All @@ -472,7 +481,7 @@ pub mod tests {
fn test_qml_metadata_singleton() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_singleton)]
struct MyObject;
pub struct MyObject;
});
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
assert_eq!(
Expand All @@ -492,7 +501,7 @@ pub mod tests {
fn test_qml_metadata_uncreatable() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_uncreatable)]
struct MyObject;
pub struct MyObject;
});
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
assert_eq!(
Expand All @@ -512,7 +521,7 @@ pub mod tests {
fn test_qml_metadata_no_version() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_uri = "foo.bar")]
struct MyObject;
pub struct MyObject;
});
assert!(ParsedQObject::from_struct(&item, 0).is_err());
}
Expand All @@ -521,7 +530,7 @@ pub mod tests {
fn test_qml_metadata_no_uri() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_version = "1.0")]
struct MyObject;
pub struct MyObject;
});
assert!(ParsedQObject::from_struct(&item, 0).is_err());
}
Expand All @@ -530,7 +539,7 @@ pub mod tests {
fn test_qml_metadata_only_name_no_version_no_uri() {
let item: ItemStruct = tokens_to_syn(quote! {
#[cxx_qt::qobject(qml_name = "MyQmlElement")]
struct MyObject;
pub struct MyObject;
});
assert!(ParsedQObject::from_struct(&item, 0).is_err());
}
Expand Down

0 comments on commit fbe4d03

Please sign in to comment.