// #![ feature( proc_macro_span ) ] // #![ feature( type_name_of_val ) ] // use test_tools::*; // use proc_macro_tools as TheModule; // #[ allow( unused_imports ) ] // use test_tools::*; use super::*; // use qt::*; // use proc_macro_tools::dependencies::*; // tests_impls! { #[ test ] fn tree_export_str_basic() { let exp = r#"code : std :: collections :: HashMap < i32 , i32 > : TokenStream [ Ident { sym: std, }, Punct { char: ':', spacing: Joint, }, Punct { char: ':', spacing: Alone, }, Ident { sym: collections, }, Punct { char: ':', spacing: Joint, }, Punct { char: ':', spacing: Alone, }, Ident { sym: HashMap, }, Punct { char: '<', spacing: Alone, }, Ident { sym: i32, }, Punct { char: ',', spacing: Alone, }, Ident { sym: i32, }, Punct { char: '>', spacing: Alone, }, ]"#; let code = qt!( std::collections::HashMap< i32, i32 > ); let got = TheModule::tree_export_str!( code ); // println!( "{}", got ); a_id!( got, exp ); let got = TheModule::tree_print!( code ); // println!( "{}", got ); a_id!( got, exp ); } // #[ test ] fn syn_err_basic() { // test.case( "basic" ); let err = TheModule::syn_err!( "abc" ); a_id!( err.to_string(), "abc" ); // test.case( "with span" ); let code = qt!( core::option::Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let err = TheModule::syn_err!( tree_type, "abc" ); a_id!( err.to_string(), "abc" ); // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); // test.case( "with span and args" ); let code = qt!( core::option::Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let err = TheModule::syn_err!( tree_type, "abc{}{}", "def", "ghi" ); a_id!( err.to_string(), "abcdefghi" ); // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); // test.case( "without span" ); let err = TheModule::syn_err!( _, "abc" ); a_id!( err.to_string(), "abc" ); // test.case( "without span, but with args" ); let err = TheModule::syn_err!( _, "abc{}{}", "def", "ghi" ); a_id!( err.to_string(), "abcdefghi" ); } // #[ test ] fn type_container_kind_basic() { // test.case( "core::option::Option< i32 >" ); let code = qt!( core::option::Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::No ); // test.case( "core::option::Option< Vec >" ); let code = qt!( core::option::Option< Vec > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::No ); // test.case( "alloc::vec::Vec< i32 >" ); let code = qt!( alloc::vec::Vec< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "alloc::vec::Vec" ); let code = qt!( alloc::vec::Vec ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "std::vec::Vec< i32 >" ); let code = qt!( std::vec::Vec< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "std::vec::Vec" ); let code = qt!( std::vec::Vec ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "std::Vec< i32 >" ); let code = qt!( std::Vec< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "std::Vec" ); let code = qt!( std::Vec ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::Vector ); // test.case( "not vector" ); let code = qt!( std::SomeVector< i32, i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::No ); // test.case( "hash map" ); let code = qt!( std::collections::HashMap< i32, i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::HashMap ); // test.case( "hash set" ); let code = qt!( std::collections::HashSet< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_container_kind( &tree_type ); a_id!( got, TheModule::ContainerKind::HashSet ); } // #[ test ] fn type_optional_container_kind_basic() { // test.case( "non optional not container" ); let code = qt!( i32 ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::No, false ) ); // test.case( "optional not container" ); let code = qt!( core::option::Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::No, true ) ); // test.case( "optional not container" ); let code = qt!( Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::No, true ) ); // test.case( "optional vector" ); let code = qt!( core::option::Option< Vec > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::Vector, true ) ); // test.case( "optional vector" ); let code = qt!( Option< Vec > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::Vector, true ) ); // test.case( "non optional vector" ); let code = qt!( std::Vec< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::Vector, false ) ); // test.case( "optional vector" ); let code = qt!( core::option::Option< std::collections::HashMap< i32, i32 > > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashMap, true ) ); // test.case( "optional vector" ); let code = qt!( Option< HashMap > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashMap, true ) ); // test.case( "non optional vector" ); let code = qt!( HashMap< i32, i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashMap, false ) ); // test.case( "optional vector" ); let code = qt!( core::option::Option< std::collections::HashSet< i32, i32 > > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashSet, true ) ); // test.case( "optional vector" ); let code = qt!( Option< HashSet > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashSet, true ) ); // test.case( "non optional vector" ); let code = qt!( HashSet< i32, i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_optional_container_kind( &tree_type ); a_id!( got, ( TheModule::ContainerKind::HashSet, false ) ); } // #[ test ] fn type_rightmost_basic() { // test.case( "core::option::Option< i32 >" ); let code = qt!( core::option::Option< i32 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got = TheModule::type_rightmost( &tree_type ); a_id!( got, Some( "Option".to_string() ) ); } // #[ test ] fn type_parameters_basic() { macro_rules! q { ( $( $Src : tt )+ ) => { syn::parse2::< syn::Type >( qt!( $( $Src )+ ) ).unwrap() } } // test.case( "core::option::Option< i8, i16, i32, i64 >" ); let code = qt!( core::option::Option< i8, i16, i32, i64 > ); let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..=0 ).into_iter().cloned().collect(); let exp = vec![ q!( i8 ) ]; a_id!( got, exp ); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..=1 ).into_iter().cloned().collect(); let exp = vec![ q!( i8 ), q!( i16 ) ]; a_id!( got, exp ); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..=2 ).into_iter().cloned().collect(); let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ) ]; a_id!( got, exp ); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..0 ).into_iter().cloned().collect(); let exp : Vec< syn::Type > = vec![]; a_id!( got, exp ); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..1 ).into_iter().cloned().collect(); let exp = vec![ q!( i8 ) ]; a_id!( got, exp ); let got : Vec< syn::Type > = TheModule::type_parameters( &tree_type, 0..2 ).into_iter().cloned().collect(); let exp = vec![ q!( i8 ), q!( i16 ) ]; a_id!( got, exp ); } // // fn attr_pair_single( attr : &syn::Attribute ) -> Result< ( String, syn::Lit, syn::Meta ), syn::Error > // #[test] // fn attr_pair_single_basic() -> Result< (), syn::Error > // { // use syn::spanned::Spanned; // // // test.case( "basic" ); // let input = qt! // { // #[derive( Former )] // pub struct Struct1 // { // #[former( default = 31 )] // pub int_1 : i32, // } // }; // // let ast = match syn::parse2::< syn::DeriveInput >( input ) // { // Ok( syntax_tree ) => syntax_tree, // Err( err ) => return Err( err ), // }; // // let fields = match ast.data // { // syn::Data::Struct( ref data_struct ) => match data_struct.fields // { // syn::Fields::Named( ref fields_named ) => // { // &fields_named.named // }, // _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Fields::Named( ref fields_named )" ) ), // }, // _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Data::Struct( ref data_struct )" ) ), // }; // // let attr = fields.first().ok_or_else( || err( "No field" ) )?.attrs.first().ok_or_else( || err( "No attr" ) )?; // // let ( key, val, meta ) = TheModule::attr_pair_single( &attr )?; // a_id!( key, "default".to_string() ); // a_id!( qt!( #val ).to_string(), "31".to_string() ); // let is = match meta // { // syn::Meta::List( _ ) => true, // _ => false, // }; // assert!( is ); // // return Ok( () ); // // fn err( src : &str ) -> syn::Error // { // syn::Error::new( proc_macro2::Span::call_site(), src ) // } // } // // #[test] // fn path_of() -> Result< (), syn::Error > // { // // let input = qt! // { // This::is::path // }; // let ast = match syn::parse2::< syn::Path >( input ) // { // Ok( syntax_tree ) => syntax_tree, // Err( err ) => return Err( err ), // }; // // let got = proc_macro_tools::path_of( &ast ); // a_id!( got, "This::is::path" ); // // return Ok( () ); // } } // tests_index! { tree_export_str_basic, syn_err_basic, type_container_kind_basic, type_optional_container_kind_basic, type_rightmost_basic, type_parameters_basic, // attr_pair_single_basic -> Result< (), syn::Error >, // path_of -> Result< (), syn::Error >, }