diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/inherent/src/expand.rs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/inherent/src/expand.rs')
-rw-r--r-- | third_party/rust/inherent/src/expand.rs | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/third_party/rust/inherent/src/expand.rs b/third_party/rust/inherent/src/expand.rs new file mode 100644 index 0000000000..c840123dee --- /dev/null +++ b/third_party/rust/inherent/src/expand.rs @@ -0,0 +1,138 @@ +use crate::parse::TraitImpl; +use crate::verbatim::VerbatimFn; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned}; +use syn::{Attribute, FnArg, Ident, ImplItem, Pat, Path, Signature, Visibility}; + +pub fn inherent(mut input: TraitImpl) -> TokenStream { + let impl_token = &input.impl_token; + let generics = &input.generics; + let where_clause = &input.generics.where_clause; + let trait_ = &input.trait_; + let ty = &input.self_ty; + + let fwd_methods: Vec<_> = input + .items + .iter() + .filter_map(|item| match item { + ImplItem::Fn(method) => Some(fwd_method( + trait_, + &method.attrs, + &method.vis, + &method.sig, + method.block.brace_token.span.join(), + )), + ImplItem::Verbatim(tokens) => { + if let Ok(method) = syn::parse2::<VerbatimFn>(tokens.clone()) { + Some(fwd_method( + trait_, + &method.attrs, + &method.vis, + &method.sig, + method.semi_token.span, + )) + } else { + None + } + } + _ => None, + }) + .collect(); + + input.items = input + .items + .into_iter() + .filter_map(|item| match item { + ImplItem::Fn(mut method) => { + method.vis = Visibility::Inherited; + Some(ImplItem::Fn(method)) + } + ImplItem::Verbatim(tokens) => { + if syn::parse2::<VerbatimFn>(tokens.clone()).is_ok() { + None + } else { + Some(ImplItem::Verbatim(tokens)) + } + } + item => Some(item), + }) + .collect(); + + let body = quote_spanned!(input.brace_token.span=> { #(#fwd_methods)* }); + + quote! { + #impl_token #generics #ty #where_clause #body + + #input + } +} + +fn fwd_method( + trait_: &Path, + attrs: &[Attribute], + vis: &Visibility, + sig: &Signature, + body_span: Span, +) -> TokenStream { + let constness = &sig.constness; + let asyncness = &sig.asyncness; + let unsafety = &sig.unsafety; + let abi = &sig.abi; + let fn_token = sig.fn_token; + let ident = &sig.ident; + let generics = &sig.generics; + let output = &sig.output; + let where_clause = &sig.generics.where_clause; + + let (arg_pat, arg_val): (Vec<_>, Vec<_>) = sig + .inputs + .pairs() + .enumerate() + .map(|(i, pair)| { + let (input, comma_token) = pair.into_tuple(); + match input { + FnArg::Receiver(receiver) => { + let self_token = receiver.self_token; + if receiver.reference.is_some() { + (quote!(#receiver #comma_token), quote!(#self_token)) + } else { + (quote!(#self_token #comma_token), quote!(#self_token)) + } + } + FnArg::Typed(arg) => { + let var = match arg.pat.as_ref() { + Pat::Ident(pat) => pat.ident.clone(), + _ => Ident::new(&format!("__arg{}", i), Span::call_site()), + }; + let colon_token = arg.colon_token; + let ty = &arg.ty; + (quote!(#var #colon_token #ty #comma_token), quote!(#var)) + } + } + }) + .unzip(); + + let types = generics.type_params().map(|param| ¶m.ident); + let body = quote!(<Self as #trait_>::#ident::<#(#types,)*>(#(#arg_val,)*)); + let block = quote_spanned!(body_span=> { #body }); + let args = quote_spanned!(sig.paren_token.span=> (#(#arg_pat)*)); + + let has_doc = attrs.iter().any(|attr| attr.path().is_ident("doc")); + let default_doc = if has_doc { + None + } else { + let mut link = String::new(); + for segment in &trait_.segments { + link += &segment.ident.to_string(); + link += "::"; + } + let msg = format!("See [`{}{}`]", link, ident); + Some(quote!(#[doc = #msg])) + }; + + quote! { + #(#attrs)* + #default_doc + #vis #constness #asyncness #unsafety #abi #fn_token #ident #generics #args #output #where_clause #block + } +} |