diff options
Diffstat (limited to 'mingling_macros/src')
| -rw-r--r-- | mingling_macros/src/func/gen_program.rs | 105 | ||||
| -rw-r--r-- | mingling_macros/src/func/program_comp_gen.rs | 4 | ||||
| -rw-r--r-- | mingling_macros/src/func/program_final_gen.rs | 15 |
3 files changed, 89 insertions, 35 deletions
diff --git a/mingling_macros/src/func/gen_program.rs b/mingling_macros/src/func/gen_program.rs index c5358bc..0c35318 100644 --- a/mingling_macros/src/func/gen_program.rs +++ b/mingling_macros/src/func/gen_program.rs @@ -15,33 +15,98 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream { #[cfg(not(feature = "comp"))] let comp_gen = quote! {}; + // When pathf is enabled, load the type_using.rs generated by the build script + // and emit its use statements so types from submodules are in scope. + #[cfg(feature = "pathf")] + let pathf_uses: Vec<proc_macro2::TokenStream> = { + let uses = load_pathf_uses(); + if uses.is_empty() { + // The file might not exist yet — emit a clear hint + let hint: proc_macro2::TokenStream = syn::parse_quote! { + compile_error!( + "pathf: `{}` not found or empty.\n\ + Make sure `build.rs` calls `mingling::build::analyze_and_build_type_mapping().unwrap();`\n\ + with features [\"build\", \"pathf\"] enabled." + ); + }; + vec![hint] + } else { + uses + } + }; + #[cfg(not(feature = "pathf"))] + let pathf_uses: Vec<proc_macro2::TokenStream> = Vec::new(); + + #[cfg(feature = "pathf")] + let super_use = quote! {}; + + #[cfg(not(feature = "pathf"))] + let super_use = quote! { + use super::*; + }; + TokenStream::from(quote! { - /// Alias for the current program type `crate::ThisProgram` - pub type Next = ::mingling::ChainProcess<crate::ThisProgram>; - - impl ::mingling::Routable<crate::ThisProgram> for ::mingling::ChainProcess<crate::ThisProgram> - { - fn to_chain(self) -> ::mingling::ChainProcess<crate::ThisProgram> { - match self { - ::mingling::ChainProcess::Ok((any, _)) => { - ::mingling::ChainProcess::Ok((any, mingling::NextProcess::Chain)) + pub use __this_program_impl::*; + + #[doc(hidden)] + pub mod __this_program_impl { + #super_use + #(#pathf_uses)* + + /// Alias for the current program type `ThisProgram` + pub type Next = ::mingling::ChainProcess<ThisProgram>; + + impl ::mingling::Routable<ThisProgram> for ::mingling::ChainProcess<ThisProgram> + { + fn to_chain(self) -> ::mingling::ChainProcess<ThisProgram> { + match self { + ::mingling::ChainProcess::Ok((any, _)) => { + ::mingling::ChainProcess::Ok((any, mingling::NextProcess::Chain)) + } + other => other, } - other => other, } - } - fn to_render(self) -> ::mingling::ChainProcess<crate::ThisProgram> { - match self { - ::mingling::ChainProcess::Ok((any, _)) => { - ::mingling::ChainProcess::Ok((any, mingling::NextProcess::Renderer)) + fn to_render(self) -> ::mingling::ChainProcess<ThisProgram> { + match self { + ::mingling::ChainProcess::Ok((any, _)) => { + ::mingling::ChainProcess::Ok((any, mingling::NextProcess::Renderer)) + } + other => other, } - other => other, } } - } - #comp_gen - ::mingling::macros::program_fallback_gen!(); - ::mingling::macros::program_final_gen!(); + #comp_gen + ::mingling::macros::program_fallback_gen!(); + ::mingling::macros::program_final_gen!(); + } }) } + +/// Loads `type_using.rs` generated by the pathf build script and returns each +/// `use ...;` line as a token stream, ready to be emitted in the generated output. +#[cfg(feature = "pathf")] +fn load_pathf_uses() -> Vec<proc_macro2::TokenStream> { + let out_dir = match std::env::var("OUT_DIR") { + Ok(d) => d, + Err(_) => return Vec::new(), + }; + let crate_name = match std::env::var("CARGO_PKG_NAME") { + Ok(n) => n, + Err(_) => return Vec::new(), + }; + let path = std::path::Path::new(&out_dir) + .join(&crate_name) + .join("type_using.rs"); + let content = match std::fs::read_to_string(&path) { + Ok(c) => c, + Err(_) => return Vec::new(), + }; + content + .lines() + .map(|line| line.trim().to_string()) + .filter(|line| !line.is_empty()) + .filter_map(|line| line.parse::<proc_macro2::TokenStream>().ok()) + .collect() +} diff --git a/mingling_macros/src/func/program_comp_gen.rs b/mingling_macros/src/func/program_comp_gen.rs index b6b2546..2fbb0e0 100644 --- a/mingling_macros/src/func/program_comp_gen.rs +++ b/mingling_macros/src/func/program_comp_gen.rs @@ -14,7 +14,7 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream { match read_ctx { Ok(ctx) => { let suggest = ::mingling::CompletionHelper::exec_completion::<crate::ThisProgram>(&ctx); - ::mingling::Routable::<crate::ThisProgram>::to_render(crate::CompletionSuggest::new((ctx, suggest))) + ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest::new((ctx, suggest))) } Err(_) => std::process::exit(1), } @@ -32,7 +32,7 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream { match read_ctx { Ok(ctx) => { let suggest = ::mingling::CompletionHelper::exec_completion::<crate::ThisProgram>(&ctx); - ::mingling::Routable::<crate::ThisProgram>::to_render(crate::CompletionSuggest::new((ctx, suggest))) + ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest::new((ctx, suggest))) } Err(_) => std::process::exit(1), } diff --git a/mingling_macros/src/func/program_final_gen.rs b/mingling_macros/src/func/program_final_gen.rs index e427f05..0eed1db 100644 --- a/mingling_macros/src/func/program_final_gen.rs +++ b/mingling_macros/src/func/program_final_gen.rs @@ -36,8 +36,8 @@ fn parse_entry_pair(entry: &proc_macro2::TokenStream) -> (proc_macro2::Ident, pr } /// Helper: convert a string ident into a token stream for the generated code. -/// Types are now brought into scope by `gen_program!()` via `include!()` of the -/// pathf-generated `type_using.rs`, so bare idents suffice. +/// Types are expected to be in scope (e.g. via pathf glob re-exports), so bare +/// idents suffice. fn ident_tokens(name: &str) -> proc_macro2::TokenStream { let ident = proc_macro2::Ident::new(name, proc_macro2::Span::call_site()); quote! { #ident } @@ -280,15 +280,6 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { quote! { u128 } }; - // When pathf is enabled, include the type_using.rs generated by the build - // script so that types from submodules are in scope for gen_program!(). - #[cfg(feature = "pathf")] - let pathf_include = quote! { - include!(concat!(env!("OUT_DIR"), "/", env!("CARGO_PKG_NAME"), "/type_using.rs")); - }; - #[cfg(not(feature = "pathf"))] - let pathf_include = quote! {}; - let expanded = quote! { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[repr(#repr_type)] @@ -306,8 +297,6 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { } impl ::mingling::ProgramCollect for #name { - #pathf_include - type Enum = #name; type ErrorDispatcherNotFound = ErrorDispatcherNotFound; type ErrorRendererNotFound = ErrorRendererNotFound; |
