use proc_macro::TokenStream; use quote::quote; use syn::{ DeriveInput, Token, parse::{Parse, ParseStream}, parse_macro_input, }; /// Parsed content of `#[space_root_test_generic(...)]`. struct GenericArgs { types: Vec, } impl Parse for GenericArgs { fn parse(input: ParseStream) -> syn::Result { let mut types = Vec::new(); if !input.is_empty() { types.push(input.parse()?); while !input.is_empty() { let _: Token![,] = input.parse()?; if !input.is_empty() { types.push(input.parse()?); } } } Ok(GenericArgs { types }) } } pub(crate) fn internal_space_root_test_derive(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = &input.ident; // Extract generic args from `#[space_root_test_generic(...)]` let generics = input .attrs .iter() .find(|attr| attr.path().is_ident("space_root_test_generic")) .and_then(|attr| attr.parse_args::().ok()) .unwrap_or(GenericArgs { types: Vec::new() }); // Build the turbofish segment if there are generic args let turbofish = if generics.types.is_empty() { quote! {} } else { let params = &generics.types[..]; quote! { ::< #(#params),* > } }; let test_mod_name = syn::Ident::new( &format!( "test_{}_space_root", just_fmt::snake_case!(name.to_string()) ), name.span(), ); let expanded = quote! { #[cfg(test)] mod #test_mod_name { use super::*; use shared_functions::rola_test_sandbox; use space_system::{Space, SpaceRoot, SpaceRootFindPattern}; use std::env::set_current_dir; #[test] fn test_create_space() { let sandbox = rola_test_sandbox(stringify!(#name)); set_current_dir(&*sandbox).unwrap(); let mut space = Space::new(#name #turbofish ::default()); match #name #turbofish ::get_pattern() { SpaceRootFindPattern::AbsolutePath(path_buf) => { let dir = sandbox.join("root"); println!("Redirect absolute path:"); println!(" from: `{}`", path_buf.display()); println!(" to: `{}`", dir.display()); space.set_override_pattern(Some( SpaceRootFindPattern::AbsolutePath(dir.clone()), )); println!("Checking if {} absolute directory does not exist before initialization", stringify!(#name)); assert!(!dir.exists()); space.init_here().unwrap(); println!("Checking if {} absolute directory exists after initialization", stringify!(#name)); assert!(dir.exists()); println!("\u{001b}[33;1mwarning\u{001b}[0m: Absolute path test completed in isolated environment, may not fully represent system runtime conditions"); return; }, _ => {} } println!("Checking if {} does not exist before initialization", stringify!(#name)); assert!(space.space_dir_current().is_err()); space.init_here().unwrap(); println!("Checking if {} exists after initialization", stringify!(#name)); assert!(space.space_dir_current().is_ok()); } } }; TokenStream::from(expanded) }