@@ -575,7 +575,7 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
575575 }
576576 }
577577
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 {
579579 if ( variants . kind === 'external_tag' ) {
580580 // All items must have a 'variant' attribute
581581 const items = flattenUnionMembers ( valueOf )
@@ -619,6 +619,53 @@ export default async function validateModel (apiModel: model.Model, restSpec: Ma
619619 }
620620
621621 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+ if ( type . inherits == null ) {
642+ modelError ( `Type ${ fqn ( item . type ) } must derive from a base type to be used in an untagged union` )
643+ continue
644+ }
645+
646+ baseTypes . add ( fqn ( type . inherits . type ) )
647+
648+ const baseType = getTypeDef ( type . inherits . type )
649+ if ( baseType == null ) {
650+ modelError ( `Type ${ fqn ( type . inherits . type ) } not found` )
651+ continue
652+ }
653+
654+ if ( baseType . kind !== 'interface' ) {
655+ modelError ( `Type ${ fqn ( type . inherits . type ) } must be an interface to be used as the base class of another interface` )
656+ continue
657+ }
658+
659+ if ( baseType . generics == null || baseType . generics . length === 0 ) {
660+ modelError ( 'The common base type of an untagged union must accept at least one generic type argument' )
661+ }
662+ }
663+ }
664+ }
665+
666+ if ( baseTypes . size !== 1 ) {
667+ modelError ( 'All items of an untagged union must derive from the same common base type' )
668+ }
622669 }
623670 }
624671
0 commit comments