@@ -149,7 +149,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
149
149
150
150
// Register builtin types
151
151
for ( const name of [
152
- 'string' , 'boolean' , 'number' , 'null'
152
+ 'string' , 'boolean' , 'number' , 'null' , 'void' , 'binary'
153
153
] ) {
154
154
const typeName = {
155
155
namespace : '_builtins' ,
@@ -546,33 +546,29 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
546
546
}
547
547
548
548
function validateTypeAlias ( typeDef : model . TypeAlias ) : void {
549
- const openGenerics = new Set ( typeDef . generics ?. map ( t => t . name ) )
549
+ const openGenerics = openGenericSet ( typeDef )
550
550
551
551
if ( typeDef . variants != null ) {
552
- if ( typeDef . generics != null && typeDef . generics . length !== 0 ) {
553
- modelError ( 'A tagged union should not have generic parameters' )
554
- }
555
-
556
552
if ( typeDef . type . kind !== 'union_of' ) {
557
553
modelError ( 'The "variants" tag only applies to unions' )
558
554
} else {
559
- validateTaggedUnion ( typeDef . name , typeDef . type , typeDef . variants )
555
+ validateTaggedUnion ( typeDef . name , typeDef . type , typeDef . variants , openGenerics )
560
556
}
561
557
} else {
562
558
validateValueOf ( typeDef . type , openGenerics )
563
559
}
564
560
}
565
561
566
- function validateTaggedUnion ( parentName : TypeName , valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag | model . Untagged ) : void {
562
+ function validateTaggedUnion ( parentName : TypeName , valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag | model . Untagged , openGenerics : Set < string > ) : void {
567
563
if ( variants . kind === 'external_tag' ) {
568
564
// All items must have a 'variant' attribute
569
- const items = flattenUnionMembers ( valueOf )
565
+ const items = flattenUnionMembers ( valueOf , openGenerics )
570
566
571
567
for ( const item of items ) {
572
568
if ( item . kind !== 'instance_of' ) {
573
569
modelError ( 'Items of externally tagged unions must be types with a "variant_tag" annotation' )
574
570
} else {
575
- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
571
+ validateTypeRef ( item . type , item . generics , openGenerics )
576
572
const type = getTypeDef ( item . type )
577
573
if ( type == null ) {
578
574
modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -587,13 +583,13 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
587
583
}
588
584
} else if ( variants . kind === 'internal_tag' ) {
589
585
const tagName = variants . tag
590
- const items = flattenUnionMembers ( valueOf )
586
+ const items = flattenUnionMembers ( valueOf , openGenerics )
591
587
592
588
for ( const item of items ) {
593
589
if ( item . kind !== 'instance_of' ) {
594
590
modelError ( 'Items of internally tagged unions must be type references' )
595
591
} else {
596
- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
592
+ validateTypeRef ( item . type , item . generics , openGenerics )
597
593
const type = getTypeDef ( item . type )
598
594
if ( type == null ) {
599
595
modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -606,7 +602,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
606
602
}
607
603
}
608
604
609
- validateValueOf ( valueOf , new Set ( ) )
605
+ validateValueOf ( valueOf , openGenerics )
610
606
} else if ( variants . kind === 'untagged' ) {
611
607
if ( fqn ( parentName ) !== '_types.query_dsl:DecayFunction' &&
612
608
fqn ( parentName ) !== '_types.query_dsl:DistanceFeatureQuery' &&
@@ -619,15 +615,15 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
619
615
modelError ( `Type ${ fqn ( variants . untypedVariant ) } not found` )
620
616
}
621
617
622
- const items = flattenUnionMembers ( valueOf )
618
+ const items = flattenUnionMembers ( valueOf , openGenerics )
623
619
const baseTypes = new Set < string > ( )
624
620
let foundUntyped = false
625
621
626
622
for ( const item of items ) {
627
623
if ( item . kind !== 'instance_of' ) {
628
624
modelError ( 'Items of type untagged unions must be type references' )
629
625
} else {
630
- validateTypeRef ( item . type , undefined , new Set < string > ( ) )
626
+ validateTypeRef ( item . type , item . generics , openGenerics )
631
627
const type = getTypeDef ( item . type )
632
628
if ( type == null ) {
633
629
modelError ( `Type ${ fqn ( item . type ) } not found` )
@@ -679,7 +675,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
679
675
// -----------------------------------------------------------------------------------------------
680
676
// Constituents of type definitions
681
677
682
- function openGenericSet ( typeDef : model . Request | model . Response | model . Interface ) : Set < string > {
678
+ function openGenericSet ( typeDef : model . Request | model . Response | model . Interface | model . TypeAlias ) : Set < string > {
683
679
return new Set ( ( typeDef . generics ?? [ ] ) . map ( name => fqn ( name ) ) )
684
680
}
685
681
@@ -884,7 +880,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
884
880
} else {
885
881
// tagged union: the discriminant tells us what to look for, check each member in isolation
886
882
assert ( typeDef . type . kind === 'union_of' , 'Variants are only allowed on union_of type aliases' )
887
- for ( const item of flattenUnionMembers ( typeDef . type ) ) {
883
+ for ( const item of flattenUnionMembers ( typeDef . type , new Set ( ) ) ) {
888
884
validateValueOfJsonEvents ( item )
889
885
}
890
886
@@ -899,13 +895,13 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
899
895
}
900
896
901
897
/** Build the flattened item list of potentially nested unions (this is used for large unions) */
902
- function flattenUnionMembers ( union : model . UnionOf ) : model . ValueOf [ ] {
898
+ function flattenUnionMembers ( union : model . UnionOf , openGenerics : Set < string > ) : model . ValueOf [ ] {
903
899
const allItems = new Array < model . ValueOf > ( )
904
900
905
901
function collectItems ( items : model . ValueOf [ ] ) : void {
906
902
for ( const item of items ) {
907
903
if ( item . kind !== 'instance_of' ) {
908
- validateValueOf ( item , new Set < string > ( ) )
904
+ validateValueOf ( item , openGenerics )
909
905
allItems . push ( item )
910
906
} else {
911
907
const itemType = getTypeDef ( item . type )
@@ -915,7 +911,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
915
911
// Recurse in nested union
916
912
collectItems ( itemType . type . items )
917
913
} else {
918
- validateValueOf ( item , new Set < string > ( ) )
914
+ validateValueOf ( item , openGenerics )
919
915
allItems . push ( item )
920
916
}
921
917
}
0 commit comments