@@ -121,6 +121,8 @@ pub fn is_primitive_or_known_type(name: &str) -> bool {
121121 | "DateTimeWithTimeZone"
122122 | "DateTimeUtc"
123123 | "DateTimeLocal"
124+ | "Date" // SeaORM re-export of chrono::NaiveDate
125+ | "Time" // SeaORM re-export of chrono::NaiveTime
124126 // UUID
125127 | "Uuid"
126128 // Serde JSON
@@ -175,6 +177,30 @@ pub fn resolve_type_to_absolute_path(ty: &Type, source_module_path: &[String]) -
175177 quote ! { #( #path_idents) :: * :: #type_ident #args }
176178}
177179
180+ /// Extract module path from a schema path TokenStream.
181+ ///
182+ /// The schema_path is something like `crate::models::user::Schema`.
183+ /// This returns `["crate", "models", "user"]` (excluding the final type name).
184+ pub fn extract_module_path_from_schema_path ( schema_path : & proc_macro2:: TokenStream ) -> Vec < String > {
185+ let path_str = schema_path. to_string ( ) ;
186+ // Parse segments: "crate :: models :: user :: Schema" -> ["crate", "models", "user", "Schema"]
187+ let segments: Vec < & str > = path_str
188+ . split ( "::" )
189+ . map ( |s| s. trim ( ) )
190+ . filter ( |s| !s. is_empty ( ) )
191+ . collect ( ) ;
192+
193+ // Return all but the last segment (which is "Schema" or "Entity")
194+ if segments. len ( ) > 1 {
195+ segments[ ..segments. len ( ) - 1 ]
196+ . iter ( )
197+ . map ( |s| s. to_string ( ) )
198+ . collect ( )
199+ } else {
200+ vec ! [ ]
201+ }
202+ }
203+
178204/// Extract the module path from a type (excluding the type name itself).
179205/// e.g., `crate::models::memo::Model` -> ["crate", "models", "memo"]
180206pub fn extract_module_path ( ty : & Type ) -> Vec < String > {
@@ -679,4 +705,44 @@ mod tests {
679705 let ty: syn:: Type = syn:: parse_str ( "Vec<DateTime<Utc>>" ) . unwrap ( ) ;
680706 assert ! ( is_primitive_like( & ty) ) ;
681707 }
708+
709+ // Tests for extract_module_path_from_schema_path
710+
711+ #[ rstest]
712+ #[ case( "crate :: models :: user :: Schema" , vec![ "crate" , "models" , "user" ] ) ]
713+ #[ case( "crate :: models :: nested :: deep :: Model" , vec![ "crate" , "models" , "nested" , "deep" ] ) ]
714+ #[ case( "super :: user :: Entity" , vec![ "super" , "user" ] ) ]
715+ #[ case( "super :: Model" , vec![ "super" ] ) ]
716+ #[ case( "Schema" , vec![ ] ) ]
717+ #[ case( "Model" , vec![ ] ) ]
718+ fn test_extract_module_path_from_schema_path (
719+ #[ case] path_str : & str ,
720+ #[ case] expected : Vec < & str > ,
721+ ) {
722+ let tokens: proc_macro2:: TokenStream = path_str. parse ( ) . unwrap ( ) ;
723+ let result = extract_module_path_from_schema_path ( & tokens) ;
724+ let expected: Vec < String > = expected. into_iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
725+ assert_eq ! ( result, expected) ;
726+ }
727+
728+ #[ test]
729+ fn test_extract_module_path_from_schema_path_empty ( ) {
730+ let tokens = proc_macro2:: TokenStream :: new ( ) ;
731+ let result = extract_module_path_from_schema_path ( & tokens) ;
732+ assert ! ( result. is_empty( ) ) ;
733+ }
734+
735+ #[ test]
736+ fn test_extract_module_path_from_schema_path_with_generics ( ) {
737+ // Even with generics, should extract module path correctly
738+ let tokens: proc_macro2:: TokenStream =
739+ "crate :: models :: user :: Schema < T >" . parse ( ) . unwrap ( ) ;
740+ let result = extract_module_path_from_schema_path ( & tokens) ;
741+ // Note: The current implementation splits by "::" which may include generics in last segment
742+ // This test documents current behavior
743+ assert ! ( !result. is_empty( ) ) ;
744+ assert_eq ! ( result[ 0 ] , "crate" ) ;
745+ assert_eq ! ( result[ 1 ] , "models" ) ;
746+ assert_eq ! ( result[ 2 ] , "user" ) ;
747+ }
682748}
0 commit comments