Process external specifications in Rust modules marked with the #[extern_spec] attribute. Nested modules are processed recursively. Specifications are collected from functions and function stubs. Modules are rewritten so that their name does not clash with the module they are specifying.
(item_mod: &mut syn::ItemMod, path: &mut syn::Path)
| 13 | /// Modules are rewritten so that their name does not clash with the module |
| 14 | /// they are specifying. |
| 15 | pub fn rewrite_mod(item_mod: &mut syn::ItemMod, path: &mut syn::Path) -> syn::Result<()> { |
| 16 | if item_mod.content.is_none() { |
| 17 | return Ok(()) |
| 18 | } |
| 19 | |
| 20 | path.segments.push(syn::PathSegment { ident: item_mod.ident.clone(), arguments: syn::PathArguments::None }); |
| 21 | let name_generator = NameGenerator::new(); |
| 22 | item_mod.ident = syn::Ident::new(&name_generator.generate_mod_name(&item_mod.ident), |
| 23 | item_mod.span()); |
| 24 | |
| 25 | for item in item_mod.content.as_mut().unwrap().1.iter_mut() { |
| 26 | match item { |
| 27 | syn::Item::Fn(item_fn) => { |
| 28 | rewrite_fn(item_fn, path); |
| 29 | }, |
| 30 | syn::Item::Mod(inner_mod) => { |
| 31 | rewrite_mod(inner_mod, path)?; |
| 32 | }, |
| 33 | syn::Item::Verbatim(tokens) => { |
| 34 | // Transforms function stubs (functions with a `;` after the |
| 35 | // signature instead of the body) into functions, then |
| 36 | // processes them. |
| 37 | let mut new_tokens = TokenStream::new(); |
| 38 | for mut token in tokens.clone().into_iter() { |
| 39 | if let TokenTree::Punct(punct) = &mut token { |
| 40 | if punct.as_char() == ';' { |
| 41 | new_tokens.extend(Group::new(proc_macro2::Delimiter::Brace, TokenStream::new()).to_token_stream()); |
| 42 | continue; |
| 43 | } |
| 44 | } |
| 45 | new_tokens.extend(token.to_token_stream()); |
| 46 | } |
| 47 | let res: Result<syn::Item, _> = syn::parse2(new_tokens); |
| 48 | if res.is_err() { |
| 49 | return Err(syn::Error::new( |
| 50 | item.span(), |
| 51 | "invalid function signature", |
| 52 | )) |
| 53 | } |
| 54 | |
| 55 | let mut item = res.unwrap(); |
| 56 | if let syn::Item::Fn(item_fn) = &mut item { |
| 57 | rewrite_fn(item_fn, path); |
| 58 | } |
| 59 | *tokens = quote!(#item) |
| 60 | } |
| 61 | syn::Item::Use(_) => {} |
| 62 | _ => return Err(syn::Error::new( |
| 63 | item.span(), |
| 64 | "unexpected item", |
| 65 | )) |
| 66 | } |
| 67 | } |
| 68 | Ok(()) |
| 69 | } |
| 70 | |
| 71 | /// Rewrite a specification function to a call to the specified function. |
| 72 | /// The result of this rewriting is then parsed in `ExternSpecResolver`. |
nothing calls this directly
no test coverage detected