Skip to content
Open
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
15 changes: 15 additions & 0 deletions intercom-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ pub fn com_library(args: TokenStream) -> TokenStream
}
}

/// Metadata for method signature.
///
/// ```rust,ignore
/// #[com_interface]
/// pub trait IFoo {
/// #[signature(OUT, a, b, c)]
/// fn foo(&self, a: u32, b: u32, c: u32) -> ComResult<u32>;
/// }
/// ```
#[proc_macro_attribute]
pub fn com_signature(_attr: TokenStream, tokens: TokenStream) -> TokenStream
{
tokens
}

/// Derives the implementation of the trait ForeignType for a type.
#[proc_macro_derive(ForeignType)]
pub fn named_type_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream
Expand Down
13 changes: 11 additions & 2 deletions intercom-cli/src/generators/idl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ impl IdlMethod
args: method
.parameters
.iter()
.map(|arg| IdlArg::try_from(arg, opts, ctx))
.enumerate()
.map(|(idx, arg)| {
let is_last = idx == method.parameters.len() - 1;
IdlArg::try_from(arg, opts, is_last, ctx)
})
.collect::<Result<Vec<_>, _>>()?,
})
}
Expand All @@ -171,6 +175,7 @@ impl IdlArg
fn try_from(
arg: &Arg,
opts: &TypeSystemOptions,
is_last: bool,
ctx: &LibraryContext,
) -> Result<Self, GeneratorError>
{
Expand All @@ -180,7 +185,11 @@ impl IdlArg
Direction::Out => attrs.push("out"),
Direction::Retval => {
attrs.push("out");
attrs.push("retval");

// Only the last parameter in the IDL is allowed [[retval]]
if is_last {
attrs.push("retval");
}
}
Direction::Return => {
return Err("Direction::Return is invalid direction for arguments"
Expand Down
20 changes: 10 additions & 10 deletions intercom-common/src/attributes/com_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn expand_com_interface(
process_itf_variant(&itf, *ts, itf_variant, &mut output, &mut itf_output);
}

if itf.item_type == utils::InterfaceType::Trait {
if itf.item_type == model::InterfaceType::Trait {
let mut impls = vec![];
for (_, method) in itf_output.method_impls.iter() {
let method_rust_ident = &method.info.name;
Expand Down Expand Up @@ -146,7 +146,7 @@ pub fn expand_com_interface(

// Implement the ComInterface for the trait.
let iid_arms = itf_output.iid_arms;
let (deref_impl, deref_ret) = if itf.item_type == utils::InterfaceType::Trait {
let (deref_impl, deref_ret) = if itf.item_type == model::InterfaceType::Trait {
(
quote_spanned!(itf.span => com_itf),
quote_spanned!(itf.span => &( dyn #itf_path + 'static ) ),
Expand Down Expand Up @@ -313,9 +313,9 @@ fn process_itf_variant(
// Create the vtable. We've already gathered all the vtable method
// pointer fields so defining the struct is simple enough.
let itf_bound = match itf.item_type {
utils::InterfaceType::Struct => quote!(),
utils::InterfaceType::Trait if itf.implemented_by.is_some() => quote!(),
utils::InterfaceType::Trait => quote!(+ #itf_ident),
model::InterfaceType::Struct => quote!(),
model::InterfaceType::Trait if itf.implemented_by.is_some() => quote!(),
model::InterfaceType::Trait => quote!(+ #itf_ident),
};
if itf.vtable_of.is_none() {
output.push(quote_spanned!(itf.span =>
Expand Down Expand Up @@ -472,8 +472,8 @@ fn format_method_vtable_entries(
let method_impl_ident = idents::com_to_rust_method_impl(itf_ident, method_ident, ts);
let ret_ty = method_info.returnhandler.com_ty();
let generics = match itf.item_type {
utils::InterfaceType::Struct => quote!(),
utils::InterfaceType::Trait => quote!(::<I, S>),
model::InterfaceType::Struct => quote!(),
model::InterfaceType::Trait => quote!(::<I, S>),
};
let params = method_info.get_parameters_tokenstream();

Expand Down Expand Up @@ -543,8 +543,8 @@ fn create_virtual_method(
// anywya, we won't use generic parameters on struct impl based implicit
// interfaces.
let (generics, bounds, s_ref, i_ref) = match itf.item_type {
utils::InterfaceType::Struct => (quote!(), quote!(), quote!(#itf_path), quote!(#itf_path)),
utils::InterfaceType::Trait => (
model::InterfaceType::Struct => (quote!(), quote!(), quote!(#itf_path), quote!(#itf_path)),
model::InterfaceType::Trait => (
quote!(<I, S>),
quote!(
where I: ?Sized,
Expand Down Expand Up @@ -629,7 +629,7 @@ fn create_get_typeinfo_function(itf: &model::ComInterface) -> Result<TokenStream
for (ts, variant) in &itf.variants {
variant_tokens.push(create_typeinfo_for_variant(itf, *ts, &variant)?);
}
let is_impl_interface = itf.item_type == utils::InterfaceType::Struct;
let is_impl_interface = itf.item_type == model::InterfaceType::Struct;

Ok(quote_spanned!(itf.span =>
#[allow(non_snake_case)]
Expand Down
55 changes: 51 additions & 4 deletions intercom-common/src/methodinfo.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::prelude::*;
use proc_macro2::Span;
use std::rc::Rc;
use syn::{spanned::Spanned, FnArg, PathArguments, Receiver, ReturnType, Signature, Type};
use syn::{
spanned::Spanned, Attribute, FnArg, PathArguments, Receiver, ReturnType, Signature, Type,
};

use crate::ast_converters::*;
use crate::model::{ComSignature, SignatureItem};
use crate::returnhandlers::{get_return_handler, ReturnHandler};
use crate::tyhandlers::{get_ty_handler, Direction, ModelTypeSystem, TypeContext, TypeHandler};
use crate::utils;
Expand All @@ -14,6 +17,7 @@ pub enum ComMethodInfoError
TooFewArguments,
BadSelfArg,
BadArg(Box<FnArg>),
Signature,
BadReturnType,
}

Expand Down Expand Up @@ -63,6 +67,7 @@ impl RustArg
}
}

#[derive(Clone)]
pub struct ComArg
{
/// Name of the argument.
Expand Down Expand Up @@ -168,6 +173,11 @@ pub struct ComMethodInfo

/// Is the method infallible.
pub infallible: bool,

/// Parameter map for the COM parameters.
///
/// For the Nth COM-parameter, args[param_map[N]] is the respective RustArg.
pub param_map: Vec<usize>,
}

impl PartialEq for ComMethodInfo
Expand All @@ -189,6 +199,7 @@ impl ComMethodInfo
/// Constructs new COM method info from a Rust method signature.
pub fn new(
decl: &Signature,
attrs: &[Attribute],
type_system: ModelTypeSystem,
) -> Result<ComMethodInfo, ComMethodInfoError>
{
Expand All @@ -209,7 +220,7 @@ impl ComMethodInfo
};

// Process other arguments.
let args = iter
let args: Vec<RustArg> = iter
.map(|arg| {
let ty = arg
.get_ty()
Expand Down Expand Up @@ -240,6 +251,37 @@ impl ComMethodInfo
let returnhandler =
get_return_handler(&retval_type, &return_type, retval_span, type_system)
.or(Err(ComMethodInfoError::BadReturnType))?;

let signature = attrs
.iter()
.find(|attr| match attr.path.get_ident() {
Some(ident) => ident == "com_signature",
None => false,
})
.map(|attr| ComSignature::from_ast(attr.tokens.clone(), &decl.ident))
.transpose()
.map_err(|_| ComMethodInfoError::Signature)?;
let param_mapping_indices = signature
.map(|sig| {
sig.params
.iter()
.map(|p| match p {
SignatureItem::Input(ident) => args
.iter()
.enumerate()
.find(|(_, arg)| ident == &arg.name)
.map(|(idx, _)| idx)
.ok_or_else(|| ComMethodInfoError::Signature),
SignatureItem::Output(idx) => Ok(args.len() + *idx as usize),
})
.collect::<Result<Vec<_>, _>>()
})
.transpose()?
.unwrap_or_else(|| {
let range = 0..(args.len() + returnhandler.com_out_args().len());
range.collect::<Vec<_>>()
});

Ok(ComMethodInfo {
name: n,
infallible: returnhandler.is_infallible(),
Expand All @@ -253,6 +295,7 @@ impl ComMethodInfo
args,
is_unsafe: unsafety,
type_system,
param_map: param_mapping_indices,
})
}

Expand All @@ -264,7 +307,11 @@ impl ComMethodInfo
.map(|ca| ComArg::from_rustarg(ca.clone(), Direction::In, self.type_system));
let out_args = self.returnhandler.com_out_args();

in_args.chain(out_args).collect()
let all_args: Vec<_> = in_args.chain(out_args).collect();
self.param_map
.iter()
.map(|&idx| all_args[idx].clone())
.collect()
}

pub fn get_parameters_tokenstream(&self) -> TokenStream
Expand Down Expand Up @@ -405,6 +452,6 @@ mod tests
Item::Fn(ref f) => &f.sig,
_ => panic!("Code isn't function"),
};
ComMethodInfo::new(sig, ts).unwrap()
ComMethodInfo::new(sig, &vec![], ts).unwrap()
}
}
Loading