Skip to content

Commit

Permalink
refactor: QObjectName now uses naming::Name
Browse files Browse the repository at this point in the history
Part of KDAB#939
  • Loading branch information
LeonMatthesKDAB committed May 21, 2024
1 parent b3b7725 commit 402573c
Show file tree
Hide file tree
Showing 23 changed files with 116 additions and 115 deletions.
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/cpp/cxxqttype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use syn::Result;
pub fn generate(qobject_idents: &QObjectName) -> Result<GeneratedCppQObjectBlocks> {
let mut result = GeneratedCppQObjectBlocks::default();

let rust_ident = qobject_idents.rust_struct.cpp.to_string();
let rust_struct = qobject_idents.rust_struct.cxx_qualified();

result
.includes
.insert("#include <cxx-qt/type.h>".to_owned());

result
.base_classes
.push(format!("::rust::cxxqt1::CxxQtType<{rust_ident}>"));
.push(format!("::rust::cxxqt1::CxxQtType<{rust_struct}>"));

Ok(result)
}
Expand Down
3 changes: 2 additions & 1 deletion crates/cxx-qt-gen/src/generator/cpp/externcxxqt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ pub fn generate(
for block in blocks {
for signal in &block.signals {
let mut block = GeneratedCppExternCxxQtBlocks::default();
let data = generate_cpp_signal(signal, &signal.qobject_ident, type_names)?;
let qobject_name = type_names.lookup(&signal.qobject_ident)?;
let data = generate_cpp_signal(signal, qobject_name, type_names)?;
block.includes = data.includes;
// Ensure that we include MaybeLockGuard<T> that is used in multiple places
block
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn generate_cpp_methods(
type_names: &TypeNames,
) -> Result<GeneratedCppQObjectBlocks> {
let mut generated = GeneratedCppQObjectBlocks::default();
let qobject_ident = qobject_idents.cpp_class.cpp.to_string();
let qobject_ident = qobject_idents.name.cxx_unqualified();
for invokable in invokables {
let idents = QMethodName::from(invokable);
let return_cxx_ty = syn_type_to_cpp_return_type(&invokable.method.sig.output, type_names)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn generate_cpp_properties(
) -> Result<GeneratedCppQObjectBlocks> {
let mut generated = GeneratedCppQObjectBlocks::default();
let mut signals = vec![];
let qobject_ident = qobject_idents.cpp_class.cpp.to_string();
let qobject_ident = qobject_idents.name.cxx_unqualified();

for property in properties {
// Cache the idents as they are used in multiple places
Expand Down
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/cpp/property/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
pub fn generate(idents: &QPropertyName, qobject_idents: &QObjectName) -> ParsedSignal {
// 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 cpp_class_rust = &qobject_idents.name.rust_unqualified();
let notify_cpp = &idents.notify.cpp;
let notify_rust_str = idents.notify.rust.to_string();
let method: ForeignItemFn = syn::parse_quote! {
Expand All @@ -24,6 +24,6 @@ pub fn generate(idents: &QPropertyName, qobject_idents: &QObjectName) -> ParsedS
ParsedSignal::from_property_method(
method,
idents.notify.clone(),
qobject_idents.cpp_class.rust.clone(),
qobject_idents.name.rust_unqualified().clone(),
)
}
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl GeneratedCppQObject {
let qobject = structured_qobject.declaration;

// Create the base object
let qobject_idents = QObjectName::from(qobject);
let qobject_idents = QObjectName::from_qobject(qobject, type_names)?;
let namespace_idents = NamespaceName::from(qobject);
let mut generated = GeneratedCppQObject {
name: qobject.name.clone(),
Expand Down
27 changes: 13 additions & 14 deletions crates/cxx-qt-gen/src/generator/cpp/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ use crate::{
signals::{QSignalHelperName, QSignalName},
},
},
naming::cpp::syn_type_to_cpp_type,
naming::TypeNames,
naming::{cpp::syn_type_to_cpp_type, Name, TypeNames},
parser::{parameter::ParsedFunctionParameter, signals::ParsedSignal},
};
use indoc::formatdoc;
use std::collections::BTreeSet;
use syn::{Ident, Result};
use syn::Result;

#[derive(Default)]
pub struct CppSignalFragment {
Expand Down Expand Up @@ -49,7 +48,7 @@ struct Parameters {
fn parameter_types_and_values(
parameters: &[ParsedFunctionParameter],
type_names: &TypeNames,
self_ty: &Ident,
self_ty: &Name,
) -> Result<Parameters> {
let mut parameter_named_types_with_self = vec![];
let mut parameter_types_with_self = vec![];
Expand All @@ -66,7 +65,7 @@ fn parameter_types_and_values(
let parameter_named_types = parameter_named_types_with_self.join(", ");

// Insert the extra argument into the closure
let self_ty = type_names.cxx_qualified(self_ty)?;
let self_ty = self_ty.cxx_qualified();
parameter_named_types_with_self.insert(0, format!("{self_ty}& self"));
parameter_types_with_self.insert(0, format!("{self_ty}&"));
parameter_values_with_self.insert(0, "self".to_owned());
Expand All @@ -81,7 +80,7 @@ fn parameter_types_and_values(

pub fn generate_cpp_signal(
signal: &ParsedSignal,
qobject_ident: &Ident,
qobject_name: &Name,
type_names: &TypeNames,
) -> Result<CppSignalFragment> {
let mut generated = CppSignalFragment::default();
Expand All @@ -92,17 +91,17 @@ pub fn generate_cpp_signal(
.insert("#include <cxx-qt/signalhandler.h>".to_owned());

// Build a namespace that includes any namespace for the T
let qobject_ident_namespaced = type_names.cxx_qualified(qobject_ident)?;
let qobject_ident_namespaced = qobject_name.cxx_qualified();

// Prepare the idents
let idents = QSignalName::from(signal);
let idents_helper = QSignalHelperName::new(&idents, qobject_ident, type_names)?;
let idents_helper = QSignalHelperName::new(&idents, qobject_name)?;

let signal_ident = idents.name.cpp;
let free_connect_ident_cpp = idents_helper.connect_name.cpp;

// Retrieve the parameters for the signal
let parameters = parameter_types_and_values(&signal.parameters, type_names, qobject_ident)?;
let parameters = parameter_types_and_values(&signal.parameters, type_names, qobject_name)?;
let parameters_named_types = parameters.named_types;
let parameters_named_types_with_self = parameters.named_types_with_self;
let parameter_types_with_self = parameters.types_with_self;
Expand Down Expand Up @@ -196,11 +195,10 @@ pub fn generate_cpp_signals(
type_names: &TypeNames,
) -> Result<GeneratedCppQObjectBlocks> {
let mut generated = GeneratedCppQObjectBlocks::default();
let qobject_ident = &qobject_idents.cpp_class.cpp;

for signal in signals {
let mut block = GeneratedCppQObjectBlocks::default();
let data = generate_cpp_signal(signal, qobject_ident, type_names)?;
let data = generate_cpp_signal(signal, &qobject_idents.name, type_names)?;
block.includes = data.includes;
block.forward_declares_namespaced = data.forward_declares;
block.fragments = data.fragments;
Expand Down Expand Up @@ -533,7 +531,8 @@ mod tests {

let mut type_names = TypeNames::default();
type_names.mock_insert("ObjRust", None, None, None);
let generated = generate_cpp_signal(&signal, &signal.qobject_ident, &type_names).unwrap();
let qobject_name = type_names.lookup(&signal.qobject_ident).unwrap();
let generated = generate_cpp_signal(&signal, &qobject_name, &type_names).unwrap();

assert_eq!(generated.methods.len(), 0);

Expand Down Expand Up @@ -623,8 +622,8 @@ mod tests {

let mut type_names = TypeNames::default();
type_names.mock_insert("ObjRust", None, Some("ObjCpp"), Some("mynamespace"));

let generated = generate_cpp_signal(&signal, &signal.qobject_ident, &type_names).unwrap();
let qobject_name = type_names.lookup(&signal.qobject_ident).unwrap();
let generated = generate_cpp_signal(&signal, qobject_name, &type_names).unwrap();

assert_eq!(generated.methods.len(), 0);

Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use syn::Result;
pub fn generate(qobject_idents: &QObjectName) -> Result<(String, GeneratedCppQObjectBlocks)> {
let mut result = GeneratedCppQObjectBlocks::default();

let cpp_class = &qobject_idents.cpp_class.cpp;
let cpp_class = &qobject_idents.name.cxx_unqualified();
let cxx_qt_thread_ident = &qobject_idents.cxx_qt_thread_class;

result.forward_declares.push(format!(
Expand Down
76 changes: 34 additions & 42 deletions crates/cxx-qt-gen/src/generator/naming/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,62 @@
// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use crate::{generator::naming::CombinedIdent, naming::Name, parser::qobject::ParsedQObject};
use crate::{
naming::{Name, TypeNames},
parser::qobject::ParsedQObject,
};
use convert_case::{Case, Casing};
use quote::format_ident;
use syn::Ident;
use syn::{Ident, Result};

/// Names for parts of a Q_OBJECT
pub struct QObjectName {
// Store the ident so that cxx_qt_thread_method can use it later
ident: Ident,
/// The name of the C++ class
pub cpp_class: CombinedIdent,
/// The name of the Rust struct
pub rust_struct: CombinedIdent,
/// The name of the QObject itself.
pub name: Name,
/// The name of the inner Rust struct
pub rust_struct: Name,
/// The name of the CxxQtThread
pub cxx_qt_thread_class: Ident,
/// The name of the Rust closure wrapper to be passed in to CxxQtThread
pub cxx_qt_thread_queued_fn_struct: Ident,
}

impl From<&ParsedQObject> for QObjectName {
fn from(qobject: &ParsedQObject) -> Self {
Self::from_name_and_ident(&qobject.name, qobject.rust_type.clone())
impl QObjectName {
pub fn from_qobject(qobject: &ParsedQObject, type_names: &TypeNames) -> Result<Self> {
Self::from_name_and_ident(&qobject.name, &qobject.rust_type, type_names)
}
}

impl QObjectName {
pub fn from_name_and_ident(qobject_name: &Name, ident_right: Ident) -> Self {
Self {
cpp_class: CombinedIdent {
cpp: format_ident!("{}", qobject_name.cxx_unqualified()),
rust: qobject_name.rust_unqualified().clone(),
},
rust_struct: CombinedIdent::from_ident(ident_right),
pub fn from_name_and_ident(
qobject_name: &Name,
ident_right: &Ident,
type_names: &TypeNames,
) -> Result<Self> {
Ok(Self {
name: qobject_name.clone(),
rust_struct: type_names.lookup(ident_right)?.clone(),
cxx_qt_thread_class: cxx_qt_thread_class_from_ident(qobject_name.rust_unqualified()),
cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(
qobject_name.rust_unqualified(),
),
ident: qobject_name.rust_unqualified().clone(),
}
})
}

// Only for mocking in tests
#[cfg(test)]
pub fn from_idents(ident_left: Ident, ident_right: Ident) -> Self {
Self {
cpp_class: CombinedIdent::from_ident(ident_left.clone()),
rust_struct: CombinedIdent::from_ident(ident_right),
name: Name::mock(&ident_left.to_string()),
rust_struct: Name::mock(&ident_right.to_string()),
cxx_qt_thread_class: cxx_qt_thread_class_from_ident(&ident_left),
cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(&ident_left),
ident: ident_left,
}
}

/// For a given ident generate the mangled threading suffix ident
pub fn cxx_qt_thread_method(&self, suffix: &str) -> Ident {
format_ident!(
"cxx_qt_ffi_{ident}_{suffix}",
ident = self.ident.to_string().to_case(Case::Snake)
ident = self.name.cxx_unqualified().to_case(Case::Snake)
)
}
}
Expand All @@ -74,33 +72,27 @@ fn cxx_qt_thread_queued_fn_struct_from_ident(ident: &Ident) -> Ident {
format_ident!("{ident}CxxQtThreadQueuedFn")
}

impl CombinedIdent {
/// For a given ident generate the Rust and C++ names
fn from_ident(ident: Ident) -> Self {
Self {
cpp: ident.clone(),
rust: ident,
}
}
}

#[cfg(test)]
pub mod tests {
use super::*;

use crate::parser::qobject::tests::create_parsed_qobject;

pub fn create_qobjectname() -> QObjectName {
QObjectName::from(&create_parsed_qobject())
QObjectName::from_qobject(&create_parsed_qobject(), &TypeNames::mock()).unwrap()
}

#[test]
fn test_parsed_property() {
let names = QObjectName::from(&create_parsed_qobject());
assert_eq!(names.cpp_class.cpp, format_ident!("MyObject"));
assert_eq!(names.cpp_class.rust, format_ident!("MyObject"));
assert_eq!(names.rust_struct.cpp, format_ident!("MyObjectRust"));
assert_eq!(names.rust_struct.rust, format_ident!("MyObjectRust"));
let names =
QObjectName::from_qobject(&create_parsed_qobject(), &TypeNames::mock()).unwrap();
assert_eq!(names.name.cxx_unqualified(), "MyObject");
assert_eq!(names.name.rust_unqualified(), &format_ident!("MyObject"));
assert_eq!(names.rust_struct.cxx_unqualified(), "MyObjectRust");
assert_eq!(
names.rust_struct.rust_unqualified(),
&format_ident!("MyObjectRust")
);
assert_eq!(
names.cxx_qt_thread_class,
format_ident!("MyObjectCxxQtThread")
Expand Down
13 changes: 5 additions & 8 deletions crates/cxx-qt-gen/src/generator/naming/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use crate::parser::signals::ParsedSignal;
use crate::{generator::naming::CombinedIdent, naming::TypeNames};
use crate::{generator::naming::CombinedIdent, naming::Name};
use convert_case::{Case, Casing};
use quote::format_ident;
use syn::{Ident, Result};
Expand Down Expand Up @@ -52,12 +52,9 @@ pub struct QSignalHelperName {
}

impl QSignalHelperName {
pub fn new(
idents: &QSignalName,
qobject_ident: &Ident,
type_names: &TypeNames,
) -> Result<Self> {
pub fn new(idents: &QSignalName, qobject_name: &Name) -> Result<Self> {
let signal_ident = &idents.name.cpp;
let qobject_ident = qobject_name.rust_unqualified().to_string();
let handler_alias = format_ident!("{qobject_ident}CxxQtSignalHandler{signal_ident}");
let namespace = {
// This namespace will take the form of:
Expand All @@ -71,10 +68,10 @@ impl QSignalHelperName {
//
// See the comment on TypeNames::cxx_qualified for why fully qualifying is
// unfortunately not possible.
let qobject_namespace = type_names.namespace(qobject_ident)?;
let qobject_namespace = qobject_name.namespace();
let namespace: Vec<_> = qobject_namespace
.into_iter()
.chain(vec!["rust::cxxqtgen1".to_owned()])
.chain(vec!["rust::cxxqtgen1"])
.collect();

namespace.join("::")
Expand Down
8 changes: 4 additions & 4 deletions crates/cxx-qt-gen/src/generator/rust/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn generate_default_constructor(
qobject_idents: &QObjectName,
namespace: &NamespaceName,
) -> GeneratedRustFragment {
let rust_struct_ident = &qobject_idents.rust_struct.rust;
let rust_struct_ident = qobject_idents.rust_struct.rust_unqualified();

let create_rs_ident = format_ident!(
"create_rs_{object_name}",
Expand Down Expand Up @@ -189,12 +189,12 @@ pub fn generate(
let mut result = GeneratedRustFragment::default();
let namespace_internals = &namespace.internal;

let qobject_name = &qobject_idents.cpp_class.cpp;
let qobject_name_rust = &qobject_idents.cpp_class.rust;
let qobject_name = qobject_idents.name.cxx_unqualified();
let qobject_name_rust = qobject_idents.name.rust_unqualified();
let qobject_name_rust_qualified = type_names.rust_qualified(qobject_name_rust)?;
let qobject_name_snake = qobject_name.to_string().to_case(Case::Snake);

let rust_struct_name_rust = &qobject_idents.rust_struct.rust;
let rust_struct_name_rust = qobject_idents.rust_struct.rust_unqualified();

for (index, constructor) in constructors.iter().enumerate() {
let lifetime = constructor.lifetime.as_ref().map(|lifetime| {
Expand Down
6 changes: 3 additions & 3 deletions crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub fn generate(
) -> Result<GeneratedRustFragment> {
let mut blocks = GeneratedRustFragment::default();

let cpp_struct_ident = &qobject_ident.cpp_class.rust;
let rust_struct_ident = &qobject_ident.rust_struct.rust;
let cpp_struct_ident = &qobject_ident.name.rust_unqualified();
let rust_struct_ident = &qobject_ident.rust_struct.rust_unqualified();
let qualified_impl = type_names.rust_qualified(cpp_struct_ident)?;

let fragment = RustFragmentPair {
Expand Down Expand Up @@ -86,7 +86,7 @@ mod tests {
#[test]
fn test_generate_rust_cxxqttype() {
let qobject = create_parsed_qobject();
let qobject_idents = QObjectName::from(&qobject);
let qobject_idents = QObjectName::from_qobject(&qobject, &TypeNames::mock()).unwrap();

let generated = generate(&qobject_idents, &TypeNames::mock()).unwrap();

Expand Down

0 comments on commit 402573c

Please sign in to comment.