Skip to content

Place all objects and passthrough items in the same block, to pass th… #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cxx-qt-gen/bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/home/ben/cxx-qt/crates/cxx-qt-gen/src/generator/naming/property.rs
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn generate(

for &method in inherited_methods {
// Skip if the cfg attributes are not resolved to true
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &method.cfgs)? {
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &method.common_attrs.cfgs)? {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl GeneratedCppBlocks {
.iter()
.filter_map(|qobject| {
// Skip if the cfg attributes are not resolved to true
match try_eval_attributes(opt.cfg_evaluator.as_ref(), &qobject.declaration.cfgs)
match try_eval_attributes(opt.cfg_evaluator.as_ref(), &qobject.declaration.common_attrs.cfgs)
{
Ok(true) => {
Some(GeneratedCppQObject::from(qobject, &parser.type_names, opt))
Expand Down
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/cpp/qenum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn generate_declaration(
opt: &GeneratedOpt,
) -> Result<String> {
// Skip if the cfg attributes are not resolved to true
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.cfgs)? {
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.common_attrs.cfgs)? {
return Ok(String::new());
}

Expand Down Expand Up @@ -75,7 +75,7 @@ pub fn generate_on_qobject<'a>(

for qenum in qenums {
// Skip if the cfg attributes are not resolved to true
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.cfgs)? {
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &qenum.common_attrs.cfgs)? {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/cpp/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn generate_cpp_signal(
let mut generated = CppSignalFragment::default();

// Skip if the cfg attributes are not resolved to true
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &signal.cfgs)? {
if !try_eval_attributes(opt.cfg_evaluator.as_ref(), &signal.common_attrs.cfgs)? {
return Ok(generated);
}

Expand Down
135 changes: 74 additions & 61 deletions crates/cxx-qt-gen/src/generator/rust/externcxxqt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
syntax::path::path_compare_str,
};
use quote::quote;
use syn::{parse_quote, Attribute, Result};
use syn::{parse_quote, Attribute, Item, Result};

impl GeneratedRustFragment {
pub fn from_extern_cxx_qt(
Expand All @@ -22,76 +22,89 @@ impl GeneratedRustFragment {
} else {
quote! {}
};
let extern_block_docs = &extern_cxxqt_block.common_attrs.docs;

// Add the pass through blocks
let unsafety = &extern_cxxqt_block.unsafety;
let items = &extern_cxxqt_block.passthrough_items;
let mut generated = extern_cxxqt_block
.qobjects
.iter()
.map(|ty| -> Result<GeneratedRustFragment> {
let mut generated = vec![];
let qobject_names = QObjectNames::from_extern_qobject(ty, type_names)?;

generated.push(GeneratedRustFragment::generate_casting_impl(
&qobject_names,
type_names,
&ty.name,
&ty.base_class,
)?);
let mut qobject_items: Vec<Item> = vec![];
let mut cxx_qt_mod = vec![];
let mut cxx_mod = vec![];
for obj in &extern_cxxqt_block.qobjects {
let qobject_names = QObjectNames::from_extern_qobject(obj, type_names)?;

let namespace = if let Some(namespace) = &ty.name.namespace() {
quote! { #[namespace = #namespace ] }
} else {
quote! {}
};
let cpp_name = &ty.name.cxx_unqualified();
let rust_name = &ty.name.rust_unqualified();
let vis = &ty.declaration.vis;
let ident = &ty.name.rust_unqualified();
let cxx_name = if &rust_name.to_string() == cpp_name {
quote! {}
} else {
let cxx_name = cpp_name.to_string();
quote! {
#[cxx_name = #cxx_name]
}
};
let cfgs: Vec<&Attribute> = ty
.declaration
.attrs
.iter()
.filter(|attr| path_compare_str(attr.meta.path(), &["cfg"]))
.collect();
let docs: Vec<&Attribute> = ty
.declaration
.attrs
.iter()
.filter(|attr| path_compare_str(attr.meta.path(), &["doc"]))
.collect();
generated.push(GeneratedRustFragment::from_cxx_item(parse_quote! {
#extern_block_namespace
#unsafety extern "C++" {
#namespace
#cxx_name
#(#cfgs)*
#(#docs)*
#vis type #ident;
}
}));
Ok(GeneratedRustFragment::flatten(generated))
})
.collect::<Result<Vec<_>>>()?;
let casting = GeneratedRustFragment::generate_casting_impl(
&qobject_names,
type_names,
&obj.name,
&obj.base_class,
)?;
cxx_mod.extend(casting.cxx_mod_contents);
cxx_qt_mod.extend(casting.cxx_qt_mod_contents);

if !items.is_empty() {
generated.push(GeneratedRustFragment::from_cxx_item(parse_quote! {
#extern_block_namespace
#unsafety extern "C++" {
#(#items)*
let namespace = if let Some(namespace) = &obj.name.namespace() {
quote! { #[namespace = #namespace ] }
} else {
quote! {}
};
let cpp_name = &obj.name.cxx_unqualified();
let rust_name = &obj.name.rust_unqualified();
let vis = &obj.declaration.vis;
let ident = &obj.name.rust_unqualified();
let cxx_name = if &rust_name.to_string() == cpp_name {
quote! {}
} else {
let cxx_name = cpp_name.to_string();
quote! {
#[cxx_name = #cxx_name]
}
}));
};
// TODO! Can we make extract_docs return references, and then use here?
let cfgs: Vec<&Attribute> = obj
.declaration
.attrs
.iter()
.filter(|attr| path_compare_str(attr.meta.path(), &["cfg"]))
.collect();
let docs: Vec<&Attribute> = obj
.declaration
.attrs
.iter()
.filter(|attr| path_compare_str(attr.meta.path(), &["doc"]))
.collect();
qobject_items.push(parse_quote! {
#namespace
#cxx_name
#(#cfgs)*
#(#docs)*
#vis type #ident;
});
}

let passthrough_items = if !items.is_empty() {
quote! {
#(#items)*
}
} else {
quote! {}
};

cxx_mod.push(parse_quote! {
#extern_block_namespace
#(#extern_block_docs)*
#unsafety extern "C++" {
#(#qobject_items)*

#passthrough_items
}
});

let mut generated = vec![GeneratedRustFragment {
cxx_mod_contents: cxx_mod,
cxx_qt_mod_contents: cxx_qt_mod,
}];

// Build the signals
for signal in &extern_cxxqt_block.signals {
let qobject_name = type_names.lookup(&signal.qobject_ident)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/rust/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ pub fn generate(
if method.safe {
std::mem::swap(&mut unsafe_call, &mut unsafe_block);
}
let doc_comments = &method.docs;
let cfgs = &method.cfgs;
let doc_comments = &method.common_attrs.docs;
let cfgs = &method.common_attrs.cfgs;
let namespace = qobject_names.namespace_tokens();

syn::parse2(quote_spanned! {
Expand Down
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/rust/qenum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pub fn generate_cxx_mod_contents(qenums: &[ParsedQEnum]) -> Vec<Item> {
let item = &qenum.item;
let vis = &item.vis;
let variants = &item.variants;
let docs = &qenum.docs;
let cfgs = &qenum.cfgs;
let docs = &qenum.common_attrs.docs;
let cfgs = &qenum.common_attrs.cfgs;

let cxx_namespace = if namespace.is_none() {
quote! {}
Expand Down
20 changes: 16 additions & 4 deletions crates/cxx-qt-gen/src/generator/rust/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl GeneratedRustFragment {
let namespace_idents = NamespaceName::from(qobject);

let mut generated = vec![
generate_qobject_definitions(&qobject_names, &qobject.cfgs)?,
generate_qobject_definitions(&qobject_names, &qobject.common_attrs.cfgs, &qobject.common_attrs.docs)?,
generate_rust_properties(
&qobject.properties,
&qobject_names,
Expand Down Expand Up @@ -57,7 +57,7 @@ impl GeneratedRustFragment {
&qobject_names,
&namespace_idents,
type_names,
&qobject.cfgs,
&qobject.common_attrs.cfgs,
)?);
}

Expand All @@ -75,9 +75,9 @@ impl GeneratedRustFragment {
&qobject_names,
&namespace_idents,
type_names,
&qobject.cfgs,
&qobject.common_attrs.cfgs,
)?,
cxxqttype::generate(&qobject_names, type_names, &qobject.cfgs)?,
cxxqttype::generate(&qobject_names, type_names, &qobject.common_attrs.cfgs)?,
]);

Ok(GeneratedRustFragment::flatten(generated))
Expand All @@ -88,6 +88,7 @@ impl GeneratedRustFragment {
fn generate_qobject_definitions(
qobject_idents: &QObjectNames,
cfgs: &[Attribute],
docs: &[Attribute],
) -> Result<GeneratedRustFragment> {
let cpp_class_name_rust = &qobject_idents.name.rust_unqualified();
let cpp_class_name_cpp = &qobject_idents.name.cxx_unqualified();
Expand All @@ -106,6 +107,15 @@ fn generate_qobject_definitions(
}
};

let maybe_docs = if docs.is_empty() {
quote! {}
} else {
quote! {
#[doc = "\n"]
#(#docs)*
}
};

Ok(GeneratedRustFragment {
cxx_mod_contents: vec![
parse_quote! {
Expand All @@ -116,6 +126,7 @@ fn generate_qobject_definitions(
#[doc = "Use this type when referring to the QObject as a pointer"]
#[doc = "\n"]
#[doc = "See the book for more information: <https://kdab.github.io/cxx-qt/book/concepts/generated_qobject.html>"]
#maybe_docs
#namespace
#cxx_name
#(#cfgs)*
Expand All @@ -130,6 +141,7 @@ fn generate_qobject_definitions(
// but to apply it to only certain types, it is needed here too
#namespace
#(#cfgs)*
#(#docs)*
type #rust_struct_name_rust;
}
},
Expand Down
4 changes: 2 additions & 2 deletions crates/cxx-qt-gen/src/generator/rust/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ pub fn generate_rust_signal(
} else {
Some(quote! { unsafe })
};
let doc_comments = &signal.docs;
let cfgs = &signal.cfgs;
let doc_comments = &signal.common_attrs.docs;
let cfgs = &signal.common_attrs.cfgs;
let namespace = if let Some(namespace) = qobject_name.namespace() {
quote_spanned! { span=> #[namespace = #namespace ] }
} else {
Expand Down
11 changes: 8 additions & 3 deletions crates/cxx-qt-gen/src/parser/externcxxqt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ use crate::{
syntax::{attribute::attribute_get_path, expr::expr_to_string},
};
use syn::{
spanned::Spanned, Error, ForeignItem, ForeignItemFn, Ident, ItemForeignMod, Result, Token,
spanned::Spanned, Error, ForeignItem, ForeignItemFn, Ident, ItemForeignMod, Result,
Token,
};
use crate::parser::CommonAttrs;

/// Representation of an extern "C++Qt" block
#[derive(Default)]
pub struct ParsedExternCxxQt {
/// The namespace of the type in C++.
pub namespace: Option<String>,
/// All the universal top level attributes for the block
pub common_attrs: CommonAttrs,
/// Whether this block has an unsafe token
pub unsafety: Option<Token![unsafe]>,
/// Items which can be passed into the extern "C++Qt" block
Expand All @@ -36,9 +40,9 @@ impl ParsedExternCxxQt {
parent_namespace: Option<&str>,
) -> Result<Self> {
// TODO: support cfg on foreign mod blocks
let attrs = require_attributes(
let (attrs, common_attrs) = require_attributes(
&foreign_mod.attrs,
&["namespace", "auto_cxx_name", "auto_rust_name"],
&["namespace", "doc", "auto_cxx_name", "auto_rust_name"],
)?;

let auto_case = CaseConversion::from_attrs(&attrs)?;
Expand All @@ -52,6 +56,7 @@ impl ParsedExternCxxQt {

let mut extern_cxx_block = ParsedExternCxxQt {
namespace,
common_attrs,
unsafety: foreign_mod.unsafety,
..Default::default()
};
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/parser/externqobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl ParsedExternQObject {
module_ident: &Ident,
parent_namespace: Option<&str>,
) -> Result<ParsedExternQObject> {
let attributes = require_attributes(&ty.attrs, &Self::ALLOWED_ATTRS)?;
let (attributes, _common_attrs) = require_attributes(&ty.attrs, &Self::ALLOWED_ATTRS)?;

let base_class = parse_base_type(&attributes)?;

Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/parser/externrustqt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl ParsedExternRustQt {
parent_namespace: Option<&str>,
) -> Result<Self> {
// TODO: support cfg on foreign mod blocks
let attrs = require_attributes(
let (attrs, _common_attrs) = require_attributes(
&foreign_mod.attrs,
&["namespace", "auto_cxx_name", "auto_rust_name"],
)?;
Expand Down
Loading
Loading