@@ -572,10 +572,28 @@ impl ToTokens for ComponentDescription<'_> {
572572 }
573573}
574574
575+ /// Used to store possible inner field schema name and tokens if field contains any schema
576+ /// references. E.g. field: Vec<Foo> should have name: Foo::name() and tokens: Foo::schema()
577+ #[ cfg_attr( feature = "debug" , derive( Debug ) ) ]
578+ #[ derive( Default ) ]
579+ pub struct SchemaReference {
580+ name : TokenStream ,
581+ tokens : TokenStream ,
582+ }
583+
584+ impl SchemaReference {
585+ /// Check whether `name` or `tokens` is empty. Will happen if token is partially resolved as a
586+ /// reference schema. E.g. inlined schemas does not generated tokens.
587+ fn is_empty ( & self ) -> bool {
588+ self . name . is_empty ( ) || self . tokens . is_empty ( )
589+ }
590+ }
591+
575592#[ cfg_attr( feature = "debug" , derive( Debug ) ) ]
576593pub struct ComponentSchema {
577594 tokens : TokenStream ,
578595 pub name_tokens : TokenStream ,
596+ pub schema_reference : Option < SchemaReference > ,
579597}
580598
581599impl ComponentSchema {
@@ -589,6 +607,7 @@ impl ComponentSchema {
589607 ) -> Result < Self , Diagnostics > {
590608 let mut tokens = TokenStream :: new ( ) ;
591609 let mut name_tokens = TokenStream :: new ( ) ;
610+ let mut schema_reference = SchemaReference :: default ( ) ;
592611
593612 match type_tree. generic_type {
594613 Some ( GenericType :: Map ) => ComponentSchema :: map_to_tokens (
@@ -601,6 +620,7 @@ impl ComponentSchema {
601620 Some ( GenericType :: Vec | GenericType :: LinkedList | GenericType :: Set ) => {
602621 ComponentSchema :: vec_to_tokens (
603622 & mut tokens,
623+ & mut schema_reference,
604624 container,
605625 features,
606626 type_tree,
@@ -610,6 +630,7 @@ impl ComponentSchema {
610630 #[ cfg( feature = "smallvec" ) ]
611631 Some ( GenericType :: SmallVec ) => ComponentSchema :: vec_to_tokens (
612632 & mut tokens,
633+ & mut schema_reference,
613634 container,
614635 features,
615636 type_tree,
@@ -623,8 +644,7 @@ impl ComponentSchema {
623644 {
624645 features. push ( Nullable :: new ( ) . into ( ) ) ;
625646 }
626-
627- ComponentSchema :: new ( ComponentSchemaProps {
647+ let schema = ComponentSchema :: new ( ComponentSchemaProps {
628648 container,
629649 type_tree : type_tree
630650 . children
@@ -635,8 +655,13 @@ impl ComponentSchema {
635655 . expect ( "ComponentSchema generic container type should have 1 child" ) ,
636656 features,
637657 description,
638- } ) ?
639- . to_tokens ( & mut tokens) ?;
658+ } ) ?;
659+ schema. to_tokens ( & mut tokens) ?;
660+
661+ if let Some ( reference) = schema. schema_reference {
662+ schema_reference. name = reference. name ;
663+ schema_reference. tokens = reference. tokens ;
664+ }
640665 }
641666 Some ( GenericType :: Cow | GenericType :: Box | GenericType :: RefCell ) => {
642667 ComponentSchema :: new ( ComponentSchemaProps {
@@ -672,6 +697,7 @@ impl ComponentSchema {
672697 None => ComponentSchema :: non_generic_to_tokens (
673698 & mut tokens,
674699 & mut name_tokens,
700+ & mut schema_reference,
675701 container,
676702 features,
677703 type_tree,
@@ -682,6 +708,11 @@ impl ComponentSchema {
682708 Ok ( Self {
683709 tokens,
684710 name_tokens,
711+ schema_reference : if schema_reference. is_empty ( ) {
712+ None
713+ } else {
714+ Some ( schema_reference)
715+ } ,
685716 } )
686717 }
687718
@@ -764,6 +795,7 @@ impl ComponentSchema {
764795
765796 fn vec_to_tokens (
766797 tokens : & mut TokenStream ,
798+ schema_reference : & mut SchemaReference ,
767799 container : & Container ,
768800 mut features : Vec < Feature > ,
769801 type_tree : & TypeTree ,
@@ -799,8 +831,6 @@ impl ComponentSchema {
799831 child
800832 } ;
801833
802- let unique = matches ! ( type_tree. generic_type, Some ( GenericType :: Set ) ) ;
803-
804834 let component_schema = ComponentSchema :: new ( ComponentSchemaProps {
805835 container,
806836 type_tree : child,
@@ -809,7 +839,12 @@ impl ComponentSchema {
809839 } ) ?;
810840 let component_schema_tokens = as_tokens_or_diagnostics ! ( & component_schema) ;
811841
812- let unique = match unique {
842+ if let Some ( reference) = component_schema. schema_reference {
843+ schema_reference. name = reference. name ;
844+ schema_reference. tokens = reference. tokens ;
845+ } ;
846+
847+ let unique = match matches ! ( type_tree. generic_type, Some ( GenericType :: Set ) ) {
813848 true => quote ! {
814849 . unique_items( true )
815850 } ,
@@ -865,6 +900,7 @@ impl ComponentSchema {
865900 fn non_generic_to_tokens (
866901 tokens : & mut TokenStream ,
867902 name_tokens : & mut TokenStream ,
903+ schema_reference : & mut SchemaReference ,
868904 container : & Container ,
869905 mut features : Vec < Feature > ,
870906 type_tree : & TypeTree ,
@@ -987,6 +1023,8 @@ impl ComponentSchema {
9871023 }
9881024 name_tokens. extend ( quote ! { format!( "{}{}" , < #type_path as utoipa:: ToSchema >:: name( ) , #component_name_buffer) } ) ;
9891025
1026+ schema_reference. name = name_tokens. clone ( ) ;
1027+
9901028 if is_inline {
9911029 let default = pop_feature ! ( features => Feature :: Default ( _) ) ;
9921030 let default_tokens = as_tokens_or_diagnostics ! ( & default ) ;
@@ -1037,6 +1075,8 @@ impl ComponentSchema {
10371075
10381076 schema. to_tokens ( tokens) ;
10391077 } else {
1078+ schema_reference. tokens =
1079+ quote ! { <#type_path as utoipa:: PartialSchema >:: schema( ) } ;
10401080 let default = pop_feature ! ( features => Feature :: Default ( _) ) ;
10411081 let default_tokens = as_tokens_or_diagnostics ! ( & default ) ;
10421082
0 commit comments