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/macro/src/expand.rs b/macro/src/expand.rs
index 6afb548..1bb3628 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -273,7 +273,7 @@
     .unwrap_or(call);
     quote! {
         #doc
-        pub fn #ident(#(#args),*) #ret {
+        pub fn #ident(#args) #ret {
             extern "C" {
                 #decl
             }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 27aa43a..34fb851 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -116,7 +116,8 @@
             args,
             ret,
             throws,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = self;
         let Signature {
             fn_token: _,
@@ -124,9 +125,14 @@
             args: args2,
             ret: ret2,
             throws: throws2,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = other;
-        receiver == receiver2 && args == args2 && ret == ret2 && throws == throws2
+        receiver == receiver2
+            && ret == ret2
+            && throws == throws2
+            && args.len() == args2.len()
+            && args.iter().zip(args2).all(|(arg, arg2)| arg == arg2)
     }
 }
 
@@ -138,10 +144,13 @@
             args,
             ret,
             throws,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = self;
         receiver.hash(state);
-        args.hash(state);
+        for arg in args {
+            arg.hash(state);
+        }
         ret.hash(state);
         throws.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 38e21b0..0d0328b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -12,8 +12,11 @@
 mod tokens;
 pub mod types;
 
-use proc_macro2::{Ident, Span, TokenStream};
-use syn::{token::Brace, LitStr, Token};
+use self::parse::kw;
+use proc_macro2::{Ident, Span};
+use syn::punctuated::Punctuated;
+use syn::token::{Brace, Paren};
+use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -55,10 +58,11 @@
 pub struct Signature {
     pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
-    pub args: Vec<Var>,
+    pub args: Punctuated<Var, Token![,]>,
     pub ret: Option<Type>,
     pub throws: bool,
-    pub tokens: TokenStream,
+    pub paren_token: Paren,
+    pub throws_tokens: Option<(kw::Result, Token![<], Token![>])>,
 }
 
 #[derive(Eq, PartialEq, Hash)]
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));
                     }
                 }
             }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 59bb0de..51592dd 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -63,12 +63,28 @@
 
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.sig.tokens.to_tokens(tokens);
+        // Notional token range for error reporting purposes.
+        self.sig.fn_token.to_tokens(tokens);
+        self.semi_token.to_tokens(tokens);
     }
 }
 
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.tokens.to_tokens(tokens);
+        self.fn_token.to_tokens(tokens);
+        self.paren_token.surround(tokens, |tokens| {
+            self.args.to_tokens(tokens);
+        });
+        if let Some(ret) = &self.ret {
+            Token![->](self.paren_token.span).to_tokens(tokens);
+            if let Some((result, langle, rangle)) = self.throws_tokens {
+                result.to_tokens(tokens);
+                langle.to_tokens(tokens);
+                ret.to_tokens(tokens);
+                rangle.to_tokens(tokens);
+            } else {
+                ret.to_tokens(tokens);
+            }
+        }
     }
 }