Skip to content

Commit b6894d6

Browse files
ahayzen-kdabBe-ing
authored andcommitted
cxx-qt-gen: add tests for qml_singleton and qml_uncreatable
Related to #25
1 parent 781de19 commit b6894d6

File tree

3 files changed

+182
-3
lines changed

3 files changed

+182
-3
lines changed

crates/cxx-qt-gen/src/generator/cpp/qobject.rs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ impl GeneratedCppQObjectBlocks {
3737
"Q_CLASSINFO(\"QML.Element\", \"{}\")",
3838
qml_metadata.name
3939
));
40-
// TODO untested
40+
4141
if qml_metadata.uncreatable {
4242
qml_specifiers.push("Q_CLASSINFO(\"QML.Creatable\", \"false\")".to_owned());
4343
}
44-
// TODO untested
44+
4545
if qml_metadata.singleton {
4646
qml_specifiers.push("QML_SINGLETON".to_owned());
4747
}
@@ -142,6 +142,7 @@ mod tests {
142142
assert_eq!(cpp.cxx_qt_thread_ident, "MyObjectCxxQtThread");
143143
assert_eq!(cpp.namespace_internals, "cxx_qt_my_object");
144144
assert_eq!(cpp.base_class, "QObject");
145+
assert_eq!(cpp.blocks.metaobjects.len(), 0);
145146
}
146147

147148
#[test]
@@ -162,5 +163,83 @@ mod tests {
162163
.unwrap();
163164
assert_eq!(cpp.namespace_internals, "cxx_qt::cxx_qt_my_object");
164165
assert_eq!(cpp.base_class, "QStringListModel");
166+
assert_eq!(cpp.blocks.metaobjects.len(), 0);
167+
}
168+
169+
#[test]
170+
fn test_generated_cpp_qobject_named() {
171+
let module: ItemMod = tokens_to_syn(quote! {
172+
#[cxx_qt::bridge(namespace = "cxx_qt")]
173+
mod ffi {
174+
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_name = "MyQmlElement")]
175+
struct MyNamedObject;
176+
}
177+
});
178+
let parser = Parser::from(module).unwrap();
179+
180+
let cpp = GeneratedCppQObject::from(
181+
parser.cxx_qt_data.qobjects.values().next().unwrap(),
182+
&ParsedCxxMappings::default(),
183+
)
184+
.unwrap();
185+
assert_eq!(cpp.ident, "MyNamedObject");
186+
assert_eq!(cpp.blocks.metaobjects.len(), 1);
187+
assert_eq!(
188+
cpp.blocks.metaobjects[0],
189+
"Q_CLASSINFO(\"QML.Element\", \"MyQmlElement\")"
190+
);
191+
}
192+
193+
#[test]
194+
fn test_generated_cpp_qobject_singleton() {
195+
let module: ItemMod = tokens_to_syn(quote! {
196+
#[cxx_qt::bridge(namespace = "cxx_qt")]
197+
mod ffi {
198+
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)]
199+
struct MyObject;
200+
}
201+
});
202+
let parser = Parser::from(module).unwrap();
203+
204+
let cpp = GeneratedCppQObject::from(
205+
parser.cxx_qt_data.qobjects.values().next().unwrap(),
206+
&ParsedCxxMappings::default(),
207+
)
208+
.unwrap();
209+
assert_eq!(cpp.ident, "MyObject");
210+
assert_eq!(cpp.blocks.metaobjects.len(), 2);
211+
assert_eq!(
212+
cpp.blocks.metaobjects[0],
213+
"Q_CLASSINFO(\"QML.Element\", \"MyObject\")"
214+
);
215+
assert_eq!(cpp.blocks.metaobjects[1], "QML_SINGLETON");
216+
}
217+
218+
#[test]
219+
fn test_generated_cpp_qobject_uncreatable() {
220+
let module: ItemMod = tokens_to_syn(quote! {
221+
#[cxx_qt::bridge(namespace = "cxx_qt")]
222+
mod ffi {
223+
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_uncreatable)]
224+
struct MyObject;
225+
}
226+
});
227+
let parser = Parser::from(module).unwrap();
228+
229+
let cpp = GeneratedCppQObject::from(
230+
parser.cxx_qt_data.qobjects.values().next().unwrap(),
231+
&ParsedCxxMappings::default(),
232+
)
233+
.unwrap();
234+
assert_eq!(cpp.ident, "MyObject");
235+
assert_eq!(cpp.blocks.metaobjects.len(), 2);
236+
assert_eq!(
237+
cpp.blocks.metaobjects[0],
238+
"Q_CLASSINFO(\"QML.Element\", \"MyObject\")"
239+
);
240+
assert_eq!(
241+
cpp.blocks.metaobjects[1],
242+
"Q_CLASSINFO(\"QML.Creatable\", \"false\")"
243+
);
165244
}
166245
}

crates/cxx-qt-gen/src/generator/rust/qobject.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ impl GeneratedRustQObject {
9797
.append(&mut generate_rust_signals(signals_enum, &qobject_idents)?);
9898
}
9999

100+
// If this type is a singleton then we need to add an include
101+
if let Some(qml_metadata) = &qobject.qml_metadata {
102+
if qml_metadata.singleton {
103+
let fragment = RustFragmentPair {
104+
cxx_bridge: vec![quote! {
105+
unsafe extern "C++" {
106+
include!(<QtQml/QQmlEngine>);
107+
}
108+
}],
109+
implementation: vec![],
110+
};
111+
generated
112+
.blocks
113+
.cxx_mod_contents
114+
.append(&mut fragment.cxx_bridge_as_items()?);
115+
}
116+
}
117+
100118
Ok(generated)
101119
}
102120
}
@@ -164,7 +182,7 @@ mod tests {
164182
use super::*;
165183

166184
use crate::parser::Parser;
167-
use crate::tests::tokens_to_syn;
185+
use crate::tests::{assert_tokens_eq, tokens_to_syn};
168186
use syn::ItemMod;
169187

170188
#[test]
@@ -212,4 +230,46 @@ mod tests {
212230
assert_eq!(rust.namespace_internals, "cxx_qt::cxx_qt_my_object");
213231
assert_eq!(rust.rust_struct_ident, "MyObject");
214232
}
233+
234+
#[test]
235+
fn test_generated_rust_qobject_blocks_singleton() {
236+
let module: ItemMod = tokens_to_syn(quote! {
237+
#[cxx_qt::bridge(namespace = "cxx_qt")]
238+
mod ffi {
239+
#[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)]
240+
struct MyObject;
241+
}
242+
});
243+
let parser = Parser::from(module).unwrap();
244+
245+
let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap())
246+
.unwrap();
247+
assert_eq!(rust.blocks.cxx_mod_contents.len(), 3);
248+
assert_tokens_eq(
249+
&rust.blocks.cxx_mod_contents[0],
250+
quote! {
251+
unsafe extern "C++" {
252+
#[cxx_name = "MyObject"]
253+
type MyObjectQt;
254+
}
255+
},
256+
);
257+
assert_tokens_eq(
258+
&rust.blocks.cxx_mod_contents[1],
259+
quote! {
260+
extern "Rust" {
261+
#[cxx_name = "MyObjectRust"]
262+
type MyObject;
263+
}
264+
},
265+
);
266+
assert_tokens_eq(
267+
&rust.blocks.cxx_mod_contents[2],
268+
quote! {
269+
unsafe extern "C++" {
270+
include!(<QtQml/QQmlEngine>);
271+
}
272+
},
273+
);
274+
}
215275
}

crates/cxx-qt-gen/src/parser/qobject.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,46 @@ pub mod tests {
461461
);
462462
}
463463

464+
#[test]
465+
fn test_qml_metadata_singleton() {
466+
let item: ItemStruct = tokens_to_syn(quote! {
467+
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_singleton)]
468+
struct MyObject;
469+
});
470+
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
471+
assert_eq!(
472+
qobject.qml_metadata,
473+
Some(QmlElementMetadata {
474+
uri: "foo.bar".to_owned(),
475+
name: "MyObject".to_owned(),
476+
version_major: 1,
477+
version_minor: 0,
478+
uncreatable: false,
479+
singleton: true,
480+
})
481+
);
482+
}
483+
484+
#[test]
485+
fn test_qml_metadata_uncreatable() {
486+
let item: ItemStruct = tokens_to_syn(quote! {
487+
#[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_uncreatable)]
488+
struct MyObject;
489+
});
490+
let qobject = ParsedQObject::from_struct(&item, 0).unwrap();
491+
assert_eq!(
492+
qobject.qml_metadata,
493+
Some(QmlElementMetadata {
494+
uri: "foo.bar".to_owned(),
495+
name: "MyObject".to_owned(),
496+
version_major: 1,
497+
version_minor: 0,
498+
uncreatable: true,
499+
singleton: false,
500+
})
501+
);
502+
}
503+
464504
#[test]
465505
fn test_qml_metadata_no_version() {
466506
let item: ItemStruct = tokens_to_syn(quote! {

0 commit comments

Comments
 (0)