Skip to content

Commit

Permalink
WIP: cxx-qt-gen: move signals away from an enum to an extern "C++" block
Browse files Browse the repository at this point in the history
Related to KDAB#557
  • Loading branch information
ahayzen-kdab committed Jun 1, 2023
1 parent 93f313d commit d642465
Show file tree
Hide file tree
Showing 20 changed files with 424 additions and 423 deletions.
47 changes: 40 additions & 7 deletions crates/cxx-qt-gen/src/generator/cpp/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::generator::{
cpp::{qobject::GeneratedCppQObjectBlocks, types::CppType},
naming::{property::QPropertyName, qobject::QObjectName},
};
use crate::parser::{cxxqtdata::ParsedCxxMappings, property::ParsedQProperty};
use syn::Result;
use crate::{
generator::{
cpp::{qobject::GeneratedCppQObjectBlocks, types::CppType},
naming::{property::QPropertyName, qobject::QObjectName},
},
parser::signals::ParsedSignal,
};
use syn::{ForeignItemFn, Result};

use super::signal::generate_cpp_signals;

mod getter;
mod meta;
mod setter;
mod signal;

pub fn generate_cpp_properties(
properties: &Vec<ParsedQProperty>,
qobject_idents: &QObjectName,
cxx_mappings: &ParsedCxxMappings,
) -> Result<GeneratedCppQObjectBlocks> {
let mut generated = GeneratedCppQObjectBlocks::default();
let mut signals = vec![];
let qobject_ident = qobject_idents.cpp_class.cpp.to_string();

for property in properties {
// Cache the idents as they are used in multiple places
let idents = QPropertyName::from(property);
Expand All @@ -34,9 +40,36 @@ pub fn generate_cpp_properties(
generated
.methods
.push(setter::generate(&idents, &qobject_ident, &cxx_ty));
generated.methods.push(signal::generate(&idents));

// Signals
//
// We build our signal in the generation phase as we need to use the naming
// structs to build the signal name
let cpp_class_rust = &qobject_idents.cpp_class.rust;
let notify_cpp = &idents.notify.cpp;
let notify_rust_str = idents.notify.rust.to_string();
let method: ForeignItemFn = syn::parse_quote! {
#[doc = "Notify for the Q_PROPERTY"]
#[rust_name = #notify_rust_str]
fn #notify_cpp(self: Pin<&mut #cpp_class_rust>);
};
signals.push(ParsedSignal {
method,
qobject_ident: qobject_idents.cpp_class.rust.clone(),
mutable: true,
safe: true,
parameters: vec![],
ident: idents.notify,
inherit: false,
});
}

generated.append(&mut generate_cpp_signals(
&signals,
qobject_idents,
cxx_mappings,
)?);

Ok(generated)
}

Expand Down
14 changes: 0 additions & 14 deletions crates/cxx-qt-gen/src/generator/cpp/property/signal.rs

This file was deleted.

12 changes: 5 additions & 7 deletions crates/cxx-qt-gen/src/generator/cpp/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,11 @@ impl GeneratedCppQObject {
&qobject_idents,
cxx_mappings,
)?);
if let Some(signals_enum) = &qobject.signals {
generated.blocks.append(&mut generate_cpp_signals(
&signals_enum.signals,
&qobject_idents,
cxx_mappings,
)?);
}
generated.blocks.append(&mut generate_cpp_signals(
&qobject.signals,
&qobject_idents,
cxx_mappings,
)?);
generated.blocks.append(&mut inherit::generate(
&qobject.inherited_methods,
&qobject.base_class,
Expand Down
46 changes: 21 additions & 25 deletions crates/cxx-qt-gen/src/generator/naming/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use syn::Ident;

/// Names for parts of a Q_SIGNAL
pub struct QSignalName {
// TODO: this is removed
pub enum_name: Ident,
pub name: CombinedIdent,
pub emit_name: CombinedIdent,
Expand All @@ -19,19 +20,12 @@ pub struct QSignalName {

impl From<&ParsedSignal> for QSignalName {
fn from(signal: &ParsedSignal) -> Self {
// Check if there is a cxx ident that should be used
let cxx_ident = if let Some(cxx_name) = &signal.cxx_name {
format_ident!("{}", cxx_name)
} else {
signal.ident.clone()
};

Self {
enum_name: signal.ident.clone(),
name: CombinedIdent::from_signal(&signal.ident, &cxx_ident),
emit_name: CombinedIdent::emit_from_signal(&signal.ident, &cxx_ident),
connect_name: CombinedIdent::connect_from_signal(&signal.ident, &cxx_ident),
on_name: on_from_signal(&signal.ident),
enum_name: signal.ident.rust.clone(),
name: CombinedIdent::from_signal(&signal.ident),
emit_name: CombinedIdent::emit_from_signal(&signal.ident),
connect_name: CombinedIdent::connect_from_signal(&signal.ident),
on_name: on_from_signal(&signal.ident.rust),
}
}
}
Expand All @@ -42,28 +36,30 @@ fn on_from_signal(ident: &Ident) -> Ident {

impl CombinedIdent {
/// For a given signal ident generate the Rust and C++ names
fn from_signal(ident: &Ident, cxx_ident: &Ident) -> Self {
fn from_signal(ident: &CombinedIdent) -> Self {
Self {
cpp: format_ident!("{}", cxx_ident.to_string().to_case(Case::Camel)),
cpp: format_ident!("{}", ident.cpp.to_string().to_case(Case::Camel)),
// Note that signal names are in camel case so we need to convert to snake and can't clone
rust: format_ident!("{}", ident.to_string().to_case(Case::Snake)),
rust: format_ident!("{}", ident.rust.to_string().to_case(Case::Snake)),
}
}

/// For a given signal ident generate the Rust and C++ emit name
fn emit_from_signal(ident: &Ident, cxx_ident: &Ident) -> Self {
fn emit_from_signal(ident: &CombinedIdent) -> Self {
Self {
cpp: format_ident!("emit{}", cxx_ident.to_string().to_case(Case::Pascal)),
rust: format_ident!("emit_{}", ident.to_string().to_case(Case::Snake)),
cpp: format_ident!("emit{}", ident.cpp.to_string().to_case(Case::Pascal)),
// Note that the Rust emit name is the same name as the signal for now
// in the future this emit wrapper in C++ will be removed.
rust: format_ident!("{}", ident.rust.to_string().to_case(Case::Snake)),
}
}

fn connect_from_signal(ident: &Ident, cxx_ident: &Ident) -> Self {
fn connect_from_signal(ident: &CombinedIdent) -> Self {
Self {
// Use signalConnect instead of onSignal here so that we don't
// create a C++ name that is similar to the QML naming scheme for signals
cpp: format_ident!("{}Connect", cxx_ident.to_string().to_case(Case::Camel)),
rust: format_ident!("connect_{}", ident.to_string().to_case(Case::Snake)),
cpp: format_ident!("{}Connect", ident.cpp.to_string().to_case(Case::Camel)),
rust: format_ident!("connect_{}", ident.rust.to_string().to_case(Case::Snake)),
}
}
}
Expand All @@ -75,9 +71,9 @@ mod tests {
#[test]
fn test_parsed_signal() {
let qsignal = ParsedSignal {
ident: format_ident!("DataChanged"),
// TODO: this won't be pascal
ident: CombinedIdent { cpp: format_ident!("DataChanged"), rust: format_ident!("DataChanged") },
parameters: vec![],
cxx_name: None,
inherit: false,
};

Expand All @@ -98,9 +94,9 @@ mod tests {
#[test]
fn test_parsed_signal_existing_cxx_name() {
let qsignal = ParsedSignal {
ident: format_ident!("ExistingSignal"),
// TODO: this won't be pascal
ident: CombinedIdent { cpp: format_ident!("ExistingSignal"), rust: format_ident!("baseName") },
parameters: vec![],
cxx_name: Some("baseName".to_owned()),
inherit: true,
};

Expand Down
39 changes: 29 additions & 10 deletions crates/cxx-qt-gen/src/generator/rust/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@

pub mod getter;
pub mod setter;
pub mod signal;

use crate::{
generator::{
naming::{property::QPropertyName, qobject::QObjectName},
rust::qobject::GeneratedRustQObjectBlocks,
},
parser::property::ParsedQProperty,
parser::{property::ParsedQProperty, signals::ParsedSignal},
};
use syn::Result;
use syn::{ForeignItemFn, Result};

use super::signals::generate_rust_signals;

pub fn generate_rust_properties(
properties: &Vec<ParsedQProperty>,
qobject_idents: &QObjectName,
) -> Result<GeneratedRustQObjectBlocks> {
let mut generated = GeneratedRustQObjectBlocks::default();
let mut signals = vec![];

for property in properties {
let idents = QPropertyName::from(property);
Expand All @@ -44,15 +46,32 @@ pub fn generate_rust_properties(
.append(&mut setter.implementation_as_items()?);

// Signals
let notify = signal::generate(&idents, qobject_idents);
generated
.cxx_mod_contents
.append(&mut notify.cxx_bridge_as_items()?);
generated
.cxx_qt_mod_contents
.append(&mut notify.implementation_as_items()?);
//
// We build our signal in the generation phase as we need to use the naming
// structs to build the signal name
//
// TODO: make a common method on ParsedSignal::from_idents
let cpp_class_rust = &qobject_idents.cpp_class.rust;
let notify_cpp = &idents.notify.cpp;
let notify_rust_str = idents.notify.rust.to_string();
let method: ForeignItemFn = syn::parse_quote! {
#[doc = "Notify for the Q_PROPERTY"]
#[rust_name = #notify_rust_str]
fn #notify_cpp(self: Pin<&mut #cpp_class_rust>);
};
signals.push(ParsedSignal {
method,
qobject_ident: qobject_idents.cpp_class.rust.clone(),
mutable: true,
safe: true,
parameters: vec![],
ident: idents.notify,
inherit: false,
});
}

generated.append(&mut generate_rust_signals(&signals, qobject_idents)?);

Ok(generated)
}

Expand Down
34 changes: 0 additions & 34 deletions crates/cxx-qt-gen/src/generator/rust/property/signal.rs

This file was deleted.

10 changes: 4 additions & 6 deletions crates/cxx-qt-gen/src/generator/rust/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,10 @@ impl GeneratedRustQObject {
&qobject_idents,
&qobject.inherited_methods,
)?);

if let Some(signals_enum) = &qobject.signals {
generated
.blocks
.append(&mut generate_rust_signals(signals_enum, &qobject_idents)?);
}
generated.blocks.append(&mut generate_rust_signals(
&qobject.signals,
&qobject_idents,
)?);

// If this type is a singleton then we need to add an include
if let Some(qml_metadata) = &qobject.qml_metadata {
Expand Down
Loading

0 comments on commit d642465

Please sign in to comment.