From f36d9047b88e4eb61e8dae5e07dd96a0f1699739 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 30 Apr 2024 23:54:11 +0300 Subject: [PATCH] macro_tools : attr::is_standard --- .../inc/former_tests/attribute_feature.rs | 42 ++++++- .../tests/inc/former_tests/visibility.rs | 3 - module/core/former/tests/inc/mod.rs | 4 +- module/core/macro_tools/src/attr.rs | 103 ++++++++++++++++++ module/core/macro_tools/tests/inc/attr.rs | 31 +++++- 5 files changed, 172 insertions(+), 11 deletions(-) diff --git a/module/core/former/tests/inc/former_tests/attribute_feature.rs b/module/core/former/tests/inc/former_tests/attribute_feature.rs index 1747cb0fd8..3ed046a626 100644 --- a/module/core/former/tests/inc/former_tests/attribute_feature.rs +++ b/module/core/former/tests/inc/former_tests/attribute_feature.rs @@ -3,11 +3,43 @@ use super::*; // xxx : need to fix -#[ derive( former::Former ) ] -struct Foo +#[ derive( Debug, PartialEq ) ] +pub struct BaseCase { - // #[ cfg( feature = "baz" ) ] - bar : i32, + #[ cfg( feature = "enabled" ) ] + enabled : i32, + #[ cfg( feature = "disabled" ) ] + disabled : i32, } -// error => Unknown attribute #[cfg(feature = "baz")] +#[ derive( Debug, PartialEq, former::Former ) ] +// #[ debug ] +// #[ derive( Debug, PartialEq ) ] +pub struct Foo +{ + // #[ cfg( feature = "enabled" ) ] + #[ allow( dead_code ) ] + enabled : i32, + #[ cfg( feature = "disabled" ) ] + disabled : i32, +} + +// == begin of generated + +// == end of generated + +#[ test ] +fn basecase() +{ + let got = BaseCase { enabled : 13 }; + let exp = BaseCase { enabled : 13 }; + a_id!( got, exp ); +} + +// #[ test ] +// fn basic() +// { +// let got = Foo::former().enabled( 13 ).form(); +// let exp = Foo { enabled : 13 }; +// a_id!( got, exp ); +// } diff --git a/module/core/former/tests/inc/former_tests/visibility.rs b/module/core/former/tests/inc/former_tests/visibility.rs index 8908c3ee08..7df53933ac 100644 --- a/module/core/former/tests/inc/former_tests/visibility.rs +++ b/module/core/former/tests/inc/former_tests/visibility.rs @@ -4,8 +4,6 @@ #[ allow( unused_imports ) ] use super::*; -// xxx : need to fix - #[ derive( Debug, PartialEq, former::Former ) ] // #[ debug ] // #[ derive( Debug, PartialEq ) ] @@ -14,7 +12,6 @@ pub struct Foo bar : i32, } - // == begin of generated // == end of generated diff --git a/module/core/former/tests/inc/mod.rs b/module/core/former/tests/inc/mod.rs index 836fc15bde..3a0e1be899 100644 --- a/module/core/former/tests/inc/mod.rs +++ b/module/core/former/tests/inc/mod.rs @@ -32,7 +32,7 @@ mod former_tests mod attribute_perform; mod attribute_setter; mod attribute_alias; - // mod attribute_feature; // xxx : write test + mod attribute_feature; // xxx : write test mod string_slice_manual; mod string_slice; @@ -40,7 +40,7 @@ mod former_tests mod default_user_type; mod user_type_no_default; mod user_type_no_debug; - mod visibility; // xxx : write test + mod visibility; mod name_collision_former_hashmap_without_parameter; mod name_collision_former_vector_without_parameter; diff --git a/module/core/macro_tools/src/attr.rs b/module/core/macro_tools/src/attr.rs index 8a9d37cb81..c3a3cc2707 100644 --- a/module/core/macro_tools/src/attr.rs +++ b/module/core/macro_tools/src/attr.rs @@ -97,6 +97,108 @@ pub( crate ) mod private return Ok( false ) } + /// Checks if the given attribute name is a standard Rust attribute. + /// + /// Standard Rust attributes are those which are recognized and processed + /// directly by the Rust compiler. They influence various aspects of compilation, + /// including but not limited to conditional compilation, optimization hints, + /// code visibility, and procedural macro behavior. + /// + /// This function is useful when developing tools that need to interact with or + /// understand the significance of specific attributes in Rust source code, such + /// as linters, code analyzers, or procedural macros. + /// + /// This function does not cover all possible attributes but includes many of the + /// common ones that are relevant to most Rust projects. Developers are encouraged + /// to update this function as needed to suit more specialized needs, especially + /// when dealing with nightly-only compiler attributes or deprecated ones. + /// + /// # Parameters + /// - `attr_name`: A string slice that holds the name of the attribute to check. + /// + /// # Returns + /// Returns `true` if `attr_name` is a recognized standard Rust attribute. Otherwise, + /// returns `false`. + /// + /// # Examples + /// + /// Standard attributes: + /// + /// ``` + /// assert_eq!( macro_tools::attr::is_standard( "cfg" ), true ); + /// assert_eq!( macro_tools::attr::is_standard( "inline" ), true ); + /// assert_eq!( macro_tools::attr::is_standard( "derive" ), true ); + /// ``` + /// + /// Non-standard or custom attributes: + /// + /// ``` + /// assert_eq!( macro_tools::attr::is_standard( "custom_attr" ), false ); + /// assert_eq!( macro_tools::attr::is_standard( "my_attribute" ), false ); + /// ``` + /// + + pub fn is_standard<'a>( attr_name : &'a str ) -> bool + { + match attr_name + { + // Conditional compilation + "cfg" | "cfg_attr" => true, + + // Compiler instructions and optimizations + "inline" | "repr" | "derive" | "allow" | "warn" | "deny" | "forbid" => true, + + // Testing attributes + "test" | "bench" => true, + + // Documentation attributes + "doc" => true, + + // Visibility and accessibility + "pub" => true, // This would typically need context to be accurate + + // Safety and ABI + "unsafe" | "no_mangle" | "extern" => true, + + // Module and Crate configuration + "path" | "macro_use" | "crate_type" | "crate_name" => true, + + // Linking + "link" | "link_name" | "link_section" => true, + + // Usage warnings + "must_use" => true, + + // Other attributes + "cold" | "export_name" | "global_allocator" => true, + + // Module handling + "used" | "unused" => true, + + // Procedural macros and hygiene + "proc_macro" | "proc_macro_derive" | "proc_macro_attribute" => true, + + // Stability attributes + "stable" | "unstable" | "rustc_const_unstable" | "rustc_const_stable" | + "rustc_diagnostic_item" | "rustc_deprecated" | "rustc_legacy_const_generics" => true, + + // Special compiler attributes + "feature" | "non_exhaustive" => true, + + // Future compatibility + "rustc_paren_sugar" | "rustc_insignificant_dtor" => true, + + // Type system extensions + "opaque" => true, + + // Miscellaneous + "track_caller" => true, + + // Default case + _ => false, + } + } + /// /// Attribute which is inner. /// @@ -316,6 +418,7 @@ pub mod exposed { equation, has_debug, + is_standard, AttributesInner, AttributesOuter, AttributedIdent, diff --git a/module/core/macro_tools/tests/inc/attr.rs b/module/core/macro_tools/tests/inc/attr.rs index 942289e7b3..6bba6e98fc 100644 --- a/module/core/macro_tools/tests/inc/attr.rs +++ b/module/core/macro_tools/tests/inc/attr.rs @@ -4,7 +4,7 @@ use super::*; // #[ test ] -fn basic() +fn parse() { let attr : syn::Attribute = syn::parse_quote!( #[ default( 31 ) ] ); @@ -22,3 +22,32 @@ fn basic() a_id!( code_to_str!( got.right ), "31".to_string() ); } + +#[ test ] +fn is_standard_standard() +{ + // Test a selection of attributes known to be standard + assert!( is_standard( "cfg" ), "Expected 'cfg' to be a standard attribute." ); + assert!( is_standard( "derive" ), "Expected 'derive' to be a standard attribute." ); + assert!( is_standard( "inline" ), "Expected 'inline' to be a standard attribute." ); + assert!( is_standard( "test" ), "Expected 'test' to be a standard attribute." ); + assert!( is_standard( "doc" ), "Expected 'doc' to be a standard attribute." ); +} + +#[ test ] +fn is_standard_non_standard() +{ + // Test some made-up attributes that should not be standard + assert!( !is_standard( "custom_attr" ), "Expected 'custom_attr' to not be a standard attribute." ); + assert!( !is_standard( "my_attribute" ), "Expected 'my_attribute' to not be a standard attribute." ); + assert!( !is_standard( "special_feature" ), "Expected 'special_feature' to not be a standard attribute." ); +} + +#[ test ] +fn is_standard_edge_cases() +{ + // Test edge cases like empty strings or unusual input + assert!( !is_standard( "" ), "Expected empty string to not be a standard attribute." ); + assert!( !is_standard( " " ), "Expected a single space to not be a standard attribute." ); + assert!( !is_standard( "cfg_attr_extra" ), "Expected 'cfg_attr_extra' to not be a standard attribute." ); +}