@@ -544,30 +544,26 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
544544 const openGenerics = openGenericSet ( typeDef ) ;
545545
546546 if ( typeDef . variants != null ) {
547- if ( typeDef . generics != null && typeDef . generics . length !== 0 ) {
548- modelError ( 'A tagged union should not have generic parameters' )
549- }
550-
551547 if ( typeDef . type . kind !== 'union_of' ) {
552548 modelError ( 'The "variants" tag only applies to unions' )
553549 } else {
554- validateTaggedUnion ( typeDef . name , typeDef . type , typeDef . variants )
550+ validateTaggedUnion ( typeDef . name , typeDef . type , typeDef . variants , openGenerics )
555551 }
556552 } else {
557553 validateValueOf ( typeDef . type , openGenerics )
558554 }
559555 }
560556
561- function validateTaggedUnion ( parentName : TypeName , valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag | model . Untagged ) : void {
557+ function validateTaggedUnion ( parentName : TypeName , valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag | model . Untagged , openGenerics : Set < string > ) : void {
562558 if ( variants . kind === 'external_tag' ) {
563559 // All items must have a 'variant' attribute
564- const items = flattenUnionMembers ( valueOf )
560+ const items = flattenUnionMembers ( valueOf , openGenerics )
565561
566562 for ( const item of items ) {
567563 if ( item . kind !== 'instance_of' ) {
568564 modelError ( 'Items of externally tagged unions must be types with a "variant_tag" annotation' )
569565 } else {
570- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
566+ validateTypeRef ( item . type , item . generics , openGenerics )
571567 const type = getTypeDef ( item . type )
572568 if ( type == null ) {
573569 modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -582,13 +578,13 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
582578 }
583579 } else if ( variants . kind === 'internal_tag' ) {
584580 const tagName = variants . tag
585- const items = flattenUnionMembers ( valueOf )
581+ const items = flattenUnionMembers ( valueOf , openGenerics )
586582
587583 for ( const item of items ) {
588584 if ( item . kind !== 'instance_of' ) {
589585 modelError ( 'Items of internally tagged unions must be type references' )
590586 } else {
591- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
587+ validateTypeRef ( item . type , item . generics , openGenerics )
592588 const type = getTypeDef ( item . type )
593589 if ( type == null ) {
594590 modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -601,7 +597,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
601597 }
602598 }
603599
604- validateValueOf ( valueOf , new Set ( ) )
600+ validateValueOf ( valueOf , openGenerics )
605601 } else if ( variants . kind === 'untagged' ) {
606602 if ( fqn ( parentName ) !== '_types.query_dsl:DecayFunction' &&
607603 fqn ( parentName ) !== '_types.query_dsl:DistanceFeatureQuery' &&
@@ -614,15 +610,15 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
614610 modelError ( `Type ${ fqn ( variants . untypedVariant ) } not found` )
615611 }
616612
617- const items = flattenUnionMembers ( valueOf )
613+ const items = flattenUnionMembers ( valueOf , openGenerics )
618614 const baseTypes = new Set < string > ( )
619615 let foundUntyped = false
620616
621617 for ( const item of items ) {
622618 if ( item . kind !== 'instance_of' ) {
623619 modelError ( 'Items of type untagged unions must be type references' )
624620 } else {
625- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
621+ validateTypeRef ( item . type , item . generics , openGenerics )
626622 const type = getTypeDef ( item . type )
627623 if ( type == null ) {
628624 modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -879,7 +875,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
879875 } else {
880876 // tagged union: the discriminant tells us what to look for, check each member in isolation
881877 assert ( typeDef . type . kind === 'union_of' , 'Variants are only allowed on union_of type aliases' )
882- for ( const item of flattenUnionMembers ( typeDef . type ) ) {
878+ for ( const item of flattenUnionMembers ( typeDef . type , new Set ( ) ) ) {
883879 validateValueOfJsonEvents ( item )
884880 }
885881
@@ -894,13 +890,13 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
894890 }
895891
896892 /** Build the flattened item list of potentially nested unions (this is used for large unions) */
897- function flattenUnionMembers ( union : model . UnionOf ) : model . ValueOf [ ] {
893+ function flattenUnionMembers ( union : model . UnionOf , openGenerics : Set < string > ) : model . ValueOf [ ] {
898894 const allItems = new Array < model . ValueOf > ( )
899895
900896 function collectItems ( items : model . ValueOf [ ] ) : void {
901897 for ( const item of items ) {
902898 if ( item . kind !== 'instance_of' ) {
903- validateValueOf ( item , new Set < string > ( ) )
899+ validateValueOf ( item , openGenerics )
904900 allItems . push ( item )
905901 } else {
906902 const itemType = getTypeDef ( item . type )
@@ -910,7 +906,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
910906 // Recurse in nested union
911907 collectItems ( itemType . type . items )
912908 } else {
913- validateValueOf ( item , new Set < string > ( ) )
909+ validateValueOf ( item , openGenerics )
914910 allItems . push ( item )
915911 }
916912 }
0 commit comments