@@ -575,7 +575,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
575
575
}
576
576
}
577
577
578
- function validateTaggedUnion ( valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag ) : void {
578
+ function validateTaggedUnion ( valueOf : model . UnionOf , variants : model . InternalTag | model . ExternalTag | model . Untagged ) : void {
579
579
if ( variants . kind === 'external_tag' ) {
580
580
// All items must have a 'variant' attribute
581
581
const items = flattenUnionMembers ( valueOf )
@@ -619,6 +619,55 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
619
619
}
620
620
621
621
validateValueOf ( valueOf , new Set ( ) )
622
+ } else if ( variants . kind === 'untagged' ) {
623
+ const items = flattenUnionMembers ( valueOf )
624
+
625
+ const baseTypes = new Set < string > ( ) ;
626
+
627
+ for ( const item of items ) {
628
+ if ( item . kind !== 'instance_of' ) {
629
+ modelError ( 'Items of type untagged unions must be type references' )
630
+ } else {
631
+ validateTypeRef ( item . type , undefined , new Set < string > ( ) )
632
+ const type = getTypeDef ( item . type )
633
+ if ( type == null ) {
634
+ modelError ( `Type ${ fqn ( item . type ) } not found` )
635
+ } else {
636
+ if ( type . kind !== 'interface' ) {
637
+ modelError ( `Type ${ fqn ( item . type ) } must be an interface to be used in an untagged union` )
638
+ continue
639
+ }
640
+
641
+ const intf = ( type as model . Interface )
642
+
643
+ if ( ! intf . inherits ) {
644
+ modelError ( `Type ${ fqn ( item . type ) } must derive from a base type to be used in an untagged union` )
645
+ continue
646
+ }
647
+
648
+ baseTypes . add ( fqn ( intf . inherits . type ) )
649
+
650
+ const baseType = getTypeDef ( intf . inherits . type )
651
+ if ( baseType === null ) {
652
+ modelError ( `Type ${ fqn ( intf . inherits . type ) } not found` )
653
+ continue
654
+ }
655
+
656
+ if ( baseType ?. kind !== 'interface' ) {
657
+ modelError ( `Type ${ fqn ( intf . inherits . type ) } must be an interface to be used as the base class of another interface` )
658
+ continue
659
+ }
660
+
661
+ if ( ! intf . inherits . generics || intf . inherits . generics . length === 0 ) {
662
+ modelError ( 'The common base type of an untagged union must accept at least one generic type argument' )
663
+ }
664
+ }
665
+ }
666
+ }
667
+
668
+ if ( baseTypes . size !== 1 ) {
669
+ modelError ( 'All items of an untagged union must derive from the same common base type' )
670
+ }
622
671
}
623
672
}
624
673
0 commit comments