Skip to content

Commit

Permalink
cxx-qt-gen: support private signals on the extern "C++Qt"
Browse files Browse the repository at this point in the history
Related to #661
  • Loading branch information
ahayzen-kdab committed Aug 25, 2023
1 parent 91230cc commit 7ee22a9
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 17 deletions.
5 changes: 5 additions & 0 deletions crates/cxx-qt-gen/src/generator/cpp/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
}];
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -272,6 +273,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
}];
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -334,6 +336,7 @@ mod tests {
},
safe: true,
inherit: true,
private: false,
}];
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -382,6 +385,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};

let generated = generate_cpp_free_signal(&signal, &ParsedCxxMappings::default()).unwrap();
Expand Down Expand Up @@ -436,6 +440,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};

let mut cxx_mappings = ParsedCxxMappings::default();
Expand Down
2 changes: 2 additions & 0 deletions crates/cxx-qt-gen/src/generator/naming/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};

let names = QSignalName::from(&qsignal);
Expand Down Expand Up @@ -90,6 +91,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};

let names = QSignalName::from(&qsignal);
Expand Down
197 changes: 181 additions & 16 deletions crates/cxx-qt-gen/src/generator/rust/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,28 @@ pub fn generate_rust_free_signal(
std::mem::swap(&mut unsafe_call, &mut unsafe_block);
}

let mut cxx_bridge = vec![];

if !signal.private {
cxx_bridge.push(quote! {
#unsafe_block extern "C++" {
#original_method
}
});
}

cxx_bridge.push(quote! {
unsafe extern "C++" {
#[doc(hidden)]
#[namespace = #connect_namespace]
#[must_use]
#[rust_name = #free_connect_ident_rust_str]
fn #free_connect_ident_cpp(self_value: #self_type_cxx, func: #unsafe_call fn(#self_type_cxx, #(#parameters_cxx),*), conn_type: CxxQtConnectionType) -> CxxQtQMetaObjectConnection;
}
});

let fragment = RustFragmentPair {
cxx_bridge: vec![
quote! {
#unsafe_block extern "C++" {
#original_method
}
},
quote! {
unsafe extern "C++" {
#[doc(hidden)]
#[namespace = #connect_namespace]
#[must_use]
#[rust_name = #free_connect_ident_rust_str]
fn #free_connect_ident_cpp(self_value: #self_type_cxx, func: #unsafe_call fn(#self_type_cxx, #(#parameters_cxx),*), conn_type: CxxQtConnectionType) -> CxxQtQMetaObjectConnection;
}
},
],
cxx_bridge,
implementation: vec![
quote! {
impl #qualified_impl {
Expand Down Expand Up @@ -274,6 +279,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -353,6 +359,7 @@ mod tests {
},
safe: true,
inherit: false,
private: false,
};
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -426,6 +433,7 @@ mod tests {
},
safe: false,
inherit: false,
private: false,
};
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -496,6 +504,7 @@ mod tests {
},
safe: true,
inherit: true,
private: false,
};
let qobject_idents = create_qobjectname();

Expand Down Expand Up @@ -550,4 +559,160 @@ mod tests {
},
);
}

#[test]
fn test_generate_rust_signal_free() {
let qsignal = ParsedSignal {
method: parse_quote! {
fn ready(self: Pin<&mut MyObject>);
},
qobject_ident: format_ident!("MyObject"),
mutable: true,
parameters: vec![],
ident: CombinedIdent {
cpp: format_ident!("ready"),
rust: format_ident!("ready"),
},
safe: true,
inherit: false,
private: false,
};

let generated = generate_rust_free_signal(
&qsignal,
&ParsedCxxMappings::default(),
&format_ident!("ffi"),
)
.unwrap();

assert_eq!(generated.cxx_mod_contents.len(), 2);
assert_eq!(generated.cxx_qt_mod_contents.len(), 2);

assert_tokens_eq(
&generated.cxx_mod_contents[0],
quote! {
unsafe extern "C++" {
fn ready(self: Pin<&mut MyObject>);
}
},
);
assert_tokens_eq(
&generated.cxx_mod_contents[1],
quote! {
unsafe extern "C++" {
#[doc (hidden)]
#[namespace = "rust::cxxqtgen1::externcxxqt"]
#[must_use]
#[rust_name = "MyObject_connect_ready"]
fn MyObject_readyConnect(self_value: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection;
}
},
);
assert_tokens_eq(
&generated.cxx_qt_mod_contents[0],
quote! {
impl MyObject {
#[doc = "Connect the given function pointer to the signal "]
#[doc = "ready"]
#[doc = ", so that when the signal is emitted the function pointer is executed."]
#[doc = "\n"]
#[doc = "Note that this method uses a AutoConnection connection type."]
#[must_use]
pub fn on_ready(self: core::pin::Pin<&mut MyObject>, func: fn(core::pin::Pin<&mut MyObject>, )) -> cxx_qt_lib::QMetaObjectConnection
{
ffi::MyObject_connect_ready(self, func, cxx_qt_lib::ConnectionType::AutoConnection)
}
}
},
);
assert_tokens_eq(
&generated.cxx_qt_mod_contents[1],
quote! {
impl MyObject {
#[doc = "Connect the given function pointer to the signal "]
#[doc = "ready"]
#[doc = ", so that when the signal is emitted the function pointer is executed."]
#[must_use]
pub fn connect_ready(self: core::pin::Pin<&mut MyObject>, func: fn(core::pin::Pin<&mut MyObject>, ), conn_type: cxx_qt_lib::ConnectionType) -> cxx_qt_lib::QMetaObjectConnection
{
ffi::MyObject_connect_ready(self, func, conn_type)
}
}
},
);
}

#[test]
fn test_generate_rust_signal_free_private() {
let qsignal = ParsedSignal {
method: parse_quote! {
fn ready(self: Pin<&mut MyObject>);
},
qobject_ident: format_ident!("MyObject"),
mutable: true,
parameters: vec![],
ident: CombinedIdent {
cpp: format_ident!("ready"),
rust: format_ident!("ready"),
},
safe: true,
inherit: false,
private: true,
};

let generated = generate_rust_free_signal(
&qsignal,
&ParsedCxxMappings::default(),
&format_ident!("ffi"),
)
.unwrap();

assert_eq!(generated.cxx_mod_contents.len(), 1);
assert_eq!(generated.cxx_qt_mod_contents.len(), 2);

assert_tokens_eq(
&generated.cxx_mod_contents[0],
quote! {
unsafe extern "C++" {
#[doc (hidden)]
#[namespace = "rust::cxxqtgen1::externcxxqt"]
#[must_use]
#[rust_name = "MyObject_connect_ready"]
fn MyObject_readyConnect(self_value: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection;
}
},
);
assert_tokens_eq(
&generated.cxx_qt_mod_contents[0],
quote! {
impl MyObject {
#[doc = "Connect the given function pointer to the signal "]
#[doc = "ready"]
#[doc = ", so that when the signal is emitted the function pointer is executed."]
#[doc = "\n"]
#[doc = "Note that this method uses a AutoConnection connection type."]
#[must_use]
pub fn on_ready(self: core::pin::Pin<&mut MyObject>, func: fn(core::pin::Pin<&mut MyObject>, )) -> cxx_qt_lib::QMetaObjectConnection
{
ffi::MyObject_connect_ready(self, func, cxx_qt_lib::ConnectionType::AutoConnection)
}
}
},
);
assert_tokens_eq(
&generated.cxx_qt_mod_contents[1],
quote! {
impl MyObject {
#[doc = "Connect the given function pointer to the signal "]
#[doc = "ready"]
#[doc = ", so that when the signal is emitted the function pointer is executed."]
#[must_use]
pub fn connect_ready(self: core::pin::Pin<&mut MyObject>, func: fn(core::pin::Pin<&mut MyObject>, ), conn_type: cxx_qt_lib::ConnectionType) -> cxx_qt_lib::QMetaObjectConnection
{
ffi::MyObject_connect_ready(self, func, conn_type)
}
}
},
);
}
}
Loading

0 comments on commit 7ee22a9

Please sign in to comment.