Store finer grained tokens of Signature
This is required in order for function pointers like `fn(&CxxString)` to
work, which requires the cxx bridge to emit `fn(&::cxx::CxxString)`
rather than a straight copy of the input tokens.
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a00f8dd..8e674bd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,12 +4,17 @@
};
use proc_macro2::Ident;
use quote::{format_ident, quote};
+use syn::punctuated::Punctuated;
use syn::{
Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
- ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
+ ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
TypeBareFn, TypePath, TypeReference,
};
+pub mod kw {
+ syn::custom_keyword!(Result);
+}
+
pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
let mut apis = Vec::new();
for item in items {
@@ -151,8 +156,9 @@
}
let mut receiver = None;
- let mut args = Vec::new();
- for arg in &foreign_fn.sig.inputs {
+ let mut args = Punctuated::new();
+ for arg in foreign_fn.sig.inputs.pairs() {
+ let (arg, comma) = arg.into_tuple();
match arg {
FnArg::Receiver(receiver) => {
return Err(Error::new_spanned(receiver, "unsupported signature"))
@@ -164,7 +170,10 @@
};
let ty = parse_type(&arg.ty)?;
if ident != "self" {
- args.push(Var { ident, ty });
+ args.push_value(Var { ident, ty });
+ if let Some(comma) = comma {
+ args.push_punct(*comma);
+ }
continue;
}
if let Type::Ref(reference) = ty {
@@ -181,14 +190,13 @@
}
}
- let mut throws = false;
- let ret = parse_return_type(&foreign_fn.sig.output, &mut throws)?;
+ let mut throws_tokens = None;
+ let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
+ let throws = throws_tokens.is_some();
let doc = attrs::parse_doc(&foreign_fn.attrs)?;
let fn_token = foreign_fn.sig.fn_token;
let ident = foreign_fn.sig.ident.clone();
- let mut foreign_fn2 = foreign_fn.clone();
- foreign_fn2.attrs.clear();
- let tokens = quote!(#foreign_fn2);
+ let paren_token = foreign_fn.sig.paren_token;
let semi_token = foreign_fn.semi_token;
Ok(ExternFn {
@@ -201,7 +209,8 @@
args,
ret,
throws,
- tokens,
+ paren_token,
+ throws_tokens,
},
semi_token,
})
@@ -298,20 +307,24 @@
Ok(Var { ident, ty })
})
.collect::<Result<_>>()?;
- let mut throws = false;
- let ret = parse_return_type(&ty.output, &mut throws)?;
- let tokens = quote!(#ty);
+ let mut throws_tokens = None;
+ let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
+ let throws = throws_tokens.is_some();
Ok(Type::Fn(Box::new(Signature {
fn_token: ty.fn_token,
receiver: None,
args,
ret,
throws,
- tokens,
+ paren_token: ty.paren_token,
+ throws_tokens,
})))
}
-fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>> {
+fn parse_return_type(
+ ty: &ReturnType,
+ throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
+) -> Result<Option<Type>> {
let mut ret = match ty {
ReturnType::Default => return Ok(None),
ReturnType::Type(_, ret) => ret.as_ref(),
@@ -325,7 +338,8 @@
if ident == "Result" && generic.args.len() == 1 {
if let GenericArgument::Type(arg) = &generic.args[0] {
ret = arg;
- *throws = true;
+ *throws_tokens =
+ Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
}
}
}