Skip to content

Commit

Permalink
Add span to callables generation to improve error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
BenFordTytherington committed Feb 3, 2025
1 parent 76f801b commit 4e7f2ce
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 23 deletions.
10 changes: 6 additions & 4 deletions crates/cxx-qt-gen/src/generator/rust/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ pub fn generate(
})
.collect::<Vec<TokenStream>>();

let span = method.method.span();

let ident = &method.method_fields.name.rust_unqualified();
let cxx_name_string = &method.wrapper_ident().to_string();
let self_param = if method.mutable {
quote! { self: Pin<&mut #qobject_name> }
quote_spanned! { span => self: Pin<&mut #qobject_name> }
} else {
quote! { self: &#qobject_name }
quote_spanned! { span => self: &#qobject_name }
};
let return_type = &method.method.sig.output;

let mut unsafe_block = None;
let mut unsafe_call = Some(quote! { unsafe });
let mut unsafe_call = Some(quote_spanned! { span => unsafe });
if method.safe {
std::mem::swap(&mut unsafe_call, &mut unsafe_block);
}
Expand All @@ -50,7 +52,7 @@ pub fn generate(
let namespace = qobject_names.namespace_tokens();

syn::parse2(quote_spanned! {
method.method.span() =>
span =>
#unsafe_block extern "C++" {
#[cxx_name = #cxx_name_string]
#namespace
Expand Down
43 changes: 28 additions & 15 deletions crates/cxx-qt-gen/src/generator/rust/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ use crate::{
naming::{rust::syn_type_cxx_bridge_to_qualified, Name, TypeNames},
parser::signals::ParsedSignal,
};
use quote::quote;
use syn::{parse_quote, FnArg, Ident, Result, Type};
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{parse_quote, parse_quote_spanned, FnArg, Ident, Result, Type};

pub fn generate_rust_signal(
signal: &ParsedSignal,
qobject_name: &Name,
type_names: &TypeNames,
) -> Result<GeneratedRustFragment> {
let span = signal.method.span();
let idents = QSignalNames::from(signal);
let idents_helper = QSignalHelperNames::new(&idents, qobject_name)?;

Expand Down Expand Up @@ -79,7 +81,7 @@ pub fn generate_rust_signal(
.collect::<Result<_>>()?;

let self_type_cxx = if signal.mutable {
parse_quote! { Pin<&mut #qobject_name_rust> }
parse_quote_spanned! {span => Pin<&mut #qobject_name_rust> }
} else {
// CODECOV_EXCLUDE_START
unreachable!("Signals cannot be immutable right now so this cannot be reached")
Expand All @@ -103,7 +105,7 @@ pub fn generate_rust_signal(
let doc_comments = &signal.docs;
let cfgs = &signal.cfgs;
let namespace = if let Some(namespace) = qobject_name.namespace() {
quote! { #[namespace = #namespace ] }
quote_spanned! { span=> #[namespace = #namespace ] }
} else {
quote! {}
};
Expand All @@ -116,7 +118,8 @@ pub fn generate_rust_signal(

// TODO: what happens with RustQt signals, can they be private yet?
if !signal.private {
cxx_bridge.push(quote! {
cxx_bridge.push(quote_spanned! {
span=>
#unsafe_block extern "C++" {
#[cxx_name = #cpp_ident]
#(#cfgs)*
Expand All @@ -134,7 +137,8 @@ pub fn generate_rust_signal(
let signal_handler_drop = idents_helper.function_drop;
let namespace_str = idents_helper.namespace.to_string();

cxx_bridge.push(quote! {
cxx_bridge.push(quote_spanned! {
span =>
unsafe extern "C++" {
#[doc(hidden)]
#[namespace = #namespace_str]
Expand All @@ -147,7 +151,8 @@ pub fn generate_rust_signal(
}
});

cxx_bridge.push(quote! {
cxx_bridge.push(quote_spanned! {
span =>
#[namespace = #namespace_str]
extern "Rust" {
#[doc(hidden)]
Expand All @@ -161,7 +166,8 @@ pub fn generate_rust_signal(
let fragment = RustFragmentPair {
cxx_bridge,
implementation: vec![
quote! {
quote_spanned! {
span =>
impl #qualified_impl {
#[doc = "Connect the given function pointer to the signal "]
#[doc = #signal_name_cpp]
Expand All @@ -176,7 +182,8 @@ pub fn generate_rust_signal(
}
}
},
quote! {
quote_spanned! {
span =>
impl #qualified_impl {
#[doc = "Connect the given function pointer to the signal "]
#[doc = #signal_name_cpp]
Expand All @@ -193,20 +200,24 @@ pub fn generate_rust_signal(
}
}
},
quote! {
quote_spanned! {
span =>
#[doc(hidden)]
pub struct #closure_struct {}
},
quote! {
quote_spanned! {
span =>
impl cxx_qt::signalhandler::CxxQtSignalHandlerClosure for #closure_struct {
type Id = cxx::type_id!(#signal_handler_alias_namespaced_str);
type FnType = dyn FnMut(#self_type_qualified, #(#parameters_qualified_type),*) + Send;
}
},
quote! {
quote_spanned! {
span =>
use core::mem::drop as #signal_handler_drop;
},
quote! {
quote_spanned! {
span =>
fn #signal_handler_call(
handler: &mut cxx_qt::signalhandler::CxxQtSignalHandler<#closure_struct>,
self_value: #self_type_qualified,
Expand All @@ -215,10 +226,12 @@ pub fn generate_rust_signal(
handler.closure()(self_value, #(#parameters_name),*);
}
},
quote! {
quote_spanned! {
span =>
cxx_qt::static_assertions::assert_eq_align!(cxx_qt::signalhandler::CxxQtSignalHandler<#closure_struct>, usize);
},
quote! {
quote_spanned! {
span =>
cxx_qt::static_assertions::assert_eq_size!(cxx_qt::signalhandler::CxxQtSignalHandler<#closure_struct>, [usize; 2]);
},
],
Expand Down
5 changes: 1 addition & 4 deletions crates/cxx-qt-gen/src/naming/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,7 @@ impl TypeNames {
self.insert(qobject.name.clone())?;
}

// Find and register the names of any signals in extern "C++Qt"
for signal in extern_cxxqt.signals.iter() {
self.insert(signal.name.clone())?;
}
// TODO! Do we still need to find and register the names of any signals in extern "C++Qt"
}

Ok(())
Expand Down

0 comments on commit 4e7f2ce

Please sign in to comment.