Skip to content

Commit 128b0f4

Browse files
Move inlining to a separate phase which processes a Parser
- Add function call to cxx-qt-build and cxx-qt-macro - Inlining now happens after parsing and before structuring
1 parent 2b517b4 commit 128b0f4

File tree

5 files changed

+87
-61
lines changed

5 files changed

+87
-61
lines changed

crates/cxx-qt-build/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ use std::{
4343
};
4444

4545
use cxx_qt_gen::{
46-
parse_qt_file, write_cpp, write_rust, CppFragment, CxxQtItem, GeneratedCppBlocks, GeneratedOpt,
47-
GeneratedRustBlocks, Parser,
46+
parse_qt_file, qualify_self_types, write_cpp, write_rust, CppFragment, CxxQtItem,
47+
GeneratedCppBlocks, GeneratedOpt, GeneratedRustBlocks, Parser,
4848
};
4949

5050
// TODO: we need to eventually support having multiple modules defined in a single file. This
@@ -132,7 +132,10 @@ impl GeneratedCpp {
132132
}
133133
found_bridge = true;
134134

135-
let parser = Parser::from(m.clone())
135+
let mut parser = Parser::from(m.clone())
136+
.map_err(GeneratedError::from)
137+
.map_err(to_diagnostic)?;
138+
qualify_self_types(&mut parser)
136139
.map_err(GeneratedError::from)
137140
.map_err(to_diagnostic)?;
138141
let generated_cpp = GeneratedCppBlocks::from(&parser, &cxx_qt_opt)

crates/cxx-qt-gen/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub use generator::{
2121
GeneratedOpt,
2222
};
2323
pub use parser::Parser;
24+
pub use preprocessor::self_inlining::qualify_self_types;
2425
pub use syntax::{parse_qt_file, CxxQtFile, CxxQtItem};
2526
pub use writer::{cpp::write_cpp, rust::write_rust};
2627

@@ -175,7 +176,8 @@ mod tests {
175176
expected_cpp_header: &str,
176177
expected_cpp_source: &str,
177178
) {
178-
let parser = Parser::from(syn::parse_str(input).unwrap()).unwrap();
179+
let mut parser = Parser::from(syn::parse_str(input).unwrap()).unwrap();
180+
qualify_self_types(&mut parser).unwrap();
179181

180182
let mut cfg_evaluator = CfgEvaluatorTest::default();
181183
cfg_evaluator.cfgs.insert("crate", Some("cxx-qt-gen"));

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use super::qnamespace::ParsedQNamespace;
77
use super::trait_impl::TraitImpl;
88
use crate::naming::cpp::err_unsupported_item;
99
use crate::parser::CaseConversion;
10-
use crate::preprocessor::self_inlining::try_inline_self_invokables;
1110
use crate::{
1211
parser::{
1312
externcxxqt::ParsedExternCxxQt, inherit::ParsedInheritedMethod, method::ParsedMethod,
@@ -18,7 +17,6 @@ use crate::{
1817
path::path_compare_str,
1918
},
2019
};
21-
use quote::format_ident;
2220
use syn::{
2321
spanned::Spanned, Error, ForeignItem, Ident, Item, ItemEnum, ItemForeignMod, ItemImpl,
2422
ItemMacro, Meta, Result,
@@ -236,16 +234,6 @@ impl ParsedCxxQtData {
236234
}
237235
}
238236

239-
// If there is exaclty one qobject in the block, it can be inlined as a self type.
240-
let inline_self = qobjects.len() == 1;
241-
let inline_ident = qobjects
242-
.last()
243-
.map(|obj| format_ident!("{}", obj.declaration.ident_left));
244-
245-
try_inline_self_invokables(inline_self, &inline_ident, &mut methods)?;
246-
try_inline_self_invokables(inline_self, &inline_ident, &mut signals)?;
247-
try_inline_self_invokables(inline_self, &inline_ident, &mut inherited)?;
248-
249237
self.qobjects.push(qobjects);
250238
self.methods.push(methods);
251239
self.signals.push(signals);

crates/cxx-qt-gen/src/preprocessor/self_inlining.rs

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
// SPDX-License-Identifier: MIT OR Apache-2.0
55

66
use crate::parser::method::MethodFields;
7+
use crate::Parser;
78
use proc_macro2::Ident;
9+
use quote::format_ident;
810
use std::ops::DerefMut;
911
use syn::spanned::Spanned;
10-
use syn::Error;
12+
use syn::{Error, Result};
1113

1214
/// Inline any `Self` types in the methods signatures with the Ident of a qobject passed in
1315
///
@@ -41,86 +43,113 @@ pub fn try_inline_self_invokables(
4143
Ok(())
4244
}
4345

46+
/// For a given parser, attempt to inline the `Self` type used in any of the blocks with that blocks unique QObject
47+
pub fn qualify_self_types(parser: &mut Parser) -> Result<()> {
48+
let data = &mut parser.cxx_qt_data;
49+
for block in 0..data.qobjects.len() {
50+
let methods = &mut data.methods[block];
51+
let signals = &mut data.signals[block];
52+
let inherited = &mut data.inherited_methods[block];
53+
let qobjects = &data.qobjects[block];
54+
55+
let inline_self = qobjects.len() == 1;
56+
let inline_ident = qobjects
57+
.last()
58+
.map(|obj| format_ident!("{}", obj.declaration.ident_left));
59+
60+
try_inline_self_invokables(inline_self, &inline_ident, methods)?;
61+
try_inline_self_invokables(inline_self, &inline_ident, signals)?;
62+
try_inline_self_invokables(inline_self, &inline_ident, inherited)?;
63+
}
64+
65+
Ok(())
66+
}
67+
4468
#[cfg(test)]
4569
mod tests {
4670
use super::*;
47-
use crate::parser::cxxqtdata::ParsedCxxQtData;
4871
use crate::parser::method::ParsedMethod;
4972
use crate::tests::assert_parse_errors;
50-
use quote::format_ident;
51-
use syn::{parse_quote, Item};
73+
use syn::parse_quote;
5274

5375
#[test]
5476
fn test_self_inlining_ref() {
55-
let mut parsed_cxxqtdata = ParsedCxxQtData::new(format_ident!("ffi"), None);
56-
let extern_rust_qt: Item = parse_quote! {
57-
unsafe extern "RustQt" {
58-
#[qobject]
59-
type MyObject = super::T;
77+
let module = parse_quote! {
78+
#[cxx_qt::bridge]
79+
mod ffi {
80+
unsafe extern "RustQt" {
81+
#[qobject]
82+
type MyObject = super::T;
6083

61-
fn my_method(&self);
84+
fn my_method(&self);
6285

63-
#[inherit]
64-
fn my_inherited_method(&self);
86+
#[inherit]
87+
fn my_inherited_method(&self);
88+
}
6589
}
6690
};
67-
68-
parsed_cxxqtdata.parse_cxx_qt_item(extern_rust_qt).unwrap();
91+
let mut parser = Parser::from(module).unwrap();
92+
assert!(qualify_self_types(&mut parser).is_ok());
6993
}
7094

7195
#[test]
7296
fn test_self_inlining_pin() {
73-
let mut parsed_cxxqtdata = ParsedCxxQtData::new(format_ident!("ffi"), None);
74-
let extern_rust_qt: Item = parse_quote! {
75-
unsafe extern "RustQt" {
76-
#[qobject]
77-
type MyObject = super::T;
78-
79-
#[qsignal]
80-
fn my_signal(self: Pin<&mut Self>);
81-
}
82-
};
97+
let module = parse_quote! {
98+
#[cxx_qt::bridge]
99+
mod ffi {
100+
unsafe extern "RustQt" {
101+
#[qobject]
102+
type MyObject = super::T;
103+
104+
#[qsignal]
105+
fn my_signal(self: Pin<&mut Self>);
106+
}
83107

84-
let extern_cpp_qt: Item = parse_quote! {
85-
unsafe extern "C++Qt" {
86-
#[qobject]
87-
type MyObject;
108+
unsafe extern "C++Qt" {
109+
#[qobject]
110+
type MyOtherObject;
88111

89-
#[qsignal]
90-
fn my_signal(self: Pin<&mut Self>);
112+
#[qsignal]
113+
fn my_signal(self: Pin<&mut Self>);
114+
}
91115
}
92116
};
93-
94-
parsed_cxxqtdata.parse_cxx_qt_item(extern_rust_qt).unwrap();
95-
parsed_cxxqtdata.parse_cxx_qt_item(extern_cpp_qt).unwrap();
117+
let mut parser = Parser::from(module).unwrap();
118+
assert!(qualify_self_types(&mut parser).is_ok());
96119
}
97120

98121
#[test]
99122
fn test_self_inlining_methods_invalid() {
100123
assert_parse_errors! {
101-
|item| ParsedCxxQtData::new(format_ident!("ffi"), None).parse_cxx_qt_item(item) =>
124+
|item| qualify_self_types(&mut Parser::from(item)?) =>
102125
// No QObject in block
103126
{
104-
extern "RustQt" {
105-
fn my_method(&self);
127+
mod ffi {
128+
extern "RustQt" {
129+
fn my_method(&self);
130+
}
106131
}
107132
}
108133

109134
{
110-
extern "RustQt" {
111-
fn my_method(self: Pin<&mut Self>);
135+
mod ffi {
136+
extern "RustQt" {
137+
fn my_method(self: Pin<&mut Self>);
138+
}
112139
}
113140
}
114141
// More than 1 QObjects in block
115142
{
116-
extern "RustQt" {
117-
#[qobject]
118-
type MyObject = super::T;
143+
mod ffi {
144+
extern "RustQt" {
145+
#[qobject]
146+
type MyObject = super::T;
119147

120-
#[qobject]
121-
type MyOtherObject = super::S;
148+
#[qobject]
149+
type MyOtherObject = super::S;
122150

123-
fn my_method(&self);
151+
fn my_method(&self);
152+
}
124153
}
125154
}
126155
}

crates/cxx-qt-macro/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use proc_macro::TokenStream;
1111
use syn::{parse_macro_input, ItemMod};
1212

13-
use cxx_qt_gen::{write_rust, GeneratedRustBlocks, Parser};
13+
use cxx_qt_gen::{qualify_self_types, write_rust, GeneratedRustBlocks, Parser};
1414

1515
/// A procedural macro which generates a QObject for a struct inside a module.
1616
///
@@ -156,6 +156,10 @@ pub fn init_qml_module(args: TokenStream) -> TokenStream {
156156
// Take the module and C++ namespace and generate the rust code
157157
fn extract_and_generate(module: ItemMod) -> TokenStream {
158158
Parser::from(module)
159+
.and_then(|mut parser| {
160+
qualify_self_types(&mut parser)?;
161+
Ok(parser)
162+
})
159163
.and_then(|parser| GeneratedRustBlocks::from(&parser))
160164
.map(|generated_rust| write_rust(&generated_rust, None))
161165
.unwrap_or_else(|err| err.to_compile_error())

0 commit comments

Comments
 (0)