@@ -39,7 +39,7 @@ private List<TypeMember> OrderTypeMembers(
3939
4040 if ( typeMember . BaseTypeDefinitionFullyQualified == state . TypeDefinitionFullyQualified )
4141 {
42- typeMembers . Add ( MakeTypeMember ( typeMember , sb ) ) ;
42+ typeMembers . Add ( MakeTypeMember ( typeMember , null , sb ) ) ;
4343 }
4444 else
4545 {
@@ -62,7 +62,7 @@ private List<TypeMember> OrderTypeMembers(
6262 if ( typeMember . State . TypeDefinitionFullyQualified != unsortedTypeMember . BaseTypeDefinitionFullyQualified )
6363 continue ;
6464
65- var derivedType = MakeTypeMember ( unsortedTypeMember , sb ) ;
65+ var derivedType = MakeTypeMember ( unsortedTypeMember , typeMember , sb ) ;
6666 typeMember . DerivedTypes . Add ( derivedType ) ;
6767 typeMembers . Add ( derivedType ) ;
6868 unsortedTypeMembers . RemoveAt ( i ) ;
@@ -79,12 +79,13 @@ private List<TypeMember> OrderTypeMembers(
7979
8080 private static TypeMember MakeTypeMember (
8181 RegularUnionTypeMemberState typeMember ,
82+ TypeMember ? baseType ,
8283 StringBuilder sb )
8384 {
8485 var argName = typeMember . ContainingTypes
8586 . MakeFullyQualifiedArgumentName ( typeMember . Name , skipRootContainingType : true , sb ) ;
8687
87- return new TypeMember ( typeMember , argName , [ ] ) ;
88+ return new TypeMember ( typeMember , argName , baseType , [ ] ) ;
8889 }
8990
9091 public override void Generate ( CancellationToken cancellationToken )
@@ -332,19 +333,33 @@ private void GenerateIndexBasedActionSwitchBody(bool withState, bool isPartially
332333 if ( isPartially )
333334 {
334335 _sb . Append ( @"
335- if (" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @" is null)
336- break;
336+ if (" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @" is not null)
337+ {
338+ " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( "(" ) ;
339+
340+ if ( withState )
341+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
342+
343+ _sb . Append ( @"value);
344+ return;
345+ }
337346" ) ;
338- }
347+ GenerateBaseTypeActionChecks ( typeMember , withState ) ;
339348
340- _sb . Append ( @"
349+ _sb . Append ( @"
350+ break;" ) ;
351+ }
352+ else
353+ {
354+ _sb . Append ( @"
341355 " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( "(" ) ;
342356
343- if ( withState )
344- _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
357+ if ( withState )
358+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
345359
346- _sb . Append ( @"value);
360+ _sb . Append ( @"value);
347361 return;" ) ;
362+ }
348363 }
349364
350365 _sb . Append ( @"
@@ -478,18 +493,32 @@ private void GenerateIndexBasedFuncSwitchBody(bool withState, bool isPartially,
478493 if ( isPartially )
479494 {
480495 _sb . Append ( @"
481- if (" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @" is null)
482- break;
496+ if (" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @" is not null)
497+ {
498+ return " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( "(" ) ;
499+
500+ if ( withState )
501+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
502+
503+ _sb . Append ( @"value);
504+ }
483505" ) ;
484- }
485506
486- _sb . Append ( @"
507+ GenerateBaseTypeFuncChecks ( typeMember , withState ) ;
508+
509+ _sb . Append ( @"
510+ break;" ) ;
511+ }
512+ else
513+ {
514+ _sb . Append ( @"
487515 return " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( "(" ) ;
488516
489- if ( withState )
490- _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
517+ if ( withState )
518+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
491519
492- _sb . Append ( "value);" ) ;
520+ _sb . Append ( "value);" ) ;
521+ }
493522 }
494523
495524 _sb . Append ( @"
@@ -592,18 +621,22 @@ private void GenerateIndexBasedMapSwitchBody(bool isPartially, IReadOnlyList<Typ
592621 if ( isPartially )
593622 {
594623 _sb . Append ( @"
595- if (!" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @".IsSet)
596- break;
624+ if (" ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @".IsSet)
625+ {
626+ return " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( @".Value;
627+ }
597628" ) ;
598- }
599629
600- _sb . Append ( @"
601- return " ) . AppendEscaped ( typeMember . ArgumentName ) ;
630+ GenerateBaseTypeMapChecks ( typeMember ) ;
602631
603- if ( isPartially )
604- _sb . Append ( ".Value" ) ;
605-
606- _sb . Append ( ";" ) ;
632+ _sb . Append ( @"
633+ break;" ) ;
634+ }
635+ else
636+ {
637+ _sb . Append ( @"
638+ return " ) . AppendEscaped ( typeMember . ArgumentName ) . Append ( ";" ) ;
639+ }
607640 }
608641
609642 _sb . Append ( @"
@@ -651,9 +684,82 @@ private void RemoveDerivedTypes(List<TypeMember> typeMembers, TypeMember stopTyp
651684 }
652685 }
653686
654- private readonly record struct TypeMember (
687+ private void GenerateBaseTypeActionChecks ( TypeMember derivedType , bool withState )
688+ {
689+ var currentBaseType = derivedType . BaseType ;
690+
691+ while ( currentBaseType != null )
692+ {
693+ if ( ! currentBaseType . State . IsAbstract )
694+ {
695+ _sb . Append ( @"
696+ if (" ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( @" is not null)
697+ {
698+ " ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( "(" ) ;
699+
700+ if ( withState )
701+ {
702+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
703+ }
704+
705+ _sb . Append ( @"value);
706+ return;
707+ }" ) ;
708+ }
709+
710+ currentBaseType = currentBaseType . BaseType ;
711+ }
712+ }
713+
714+ private void GenerateBaseTypeFuncChecks ( TypeMember derivedType , bool withState )
715+ {
716+ var currentBaseType = derivedType . BaseType ;
717+
718+ while ( currentBaseType != null )
719+ {
720+ if ( ! currentBaseType . State . IsAbstract )
721+ {
722+ _sb . Append ( @"
723+ if (" ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( @" is not null)
724+ {
725+ return " ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( "(" ) ;
726+
727+ if ( withState )
728+ {
729+ _sb . AppendEscaped ( _state . Settings . SwitchMapStateParameterName ) . Append ( ", " ) ;
730+ }
731+
732+ _sb . Append ( @"value);
733+ }" ) ;
734+ }
735+
736+ currentBaseType = currentBaseType . BaseType ;
737+ }
738+ }
739+
740+ private void GenerateBaseTypeMapChecks ( TypeMember derivedType )
741+ {
742+ var currentBaseType = derivedType . BaseType ;
743+
744+ while ( currentBaseType != null )
745+ {
746+ if ( ! currentBaseType . State . IsAbstract )
747+ {
748+ _sb . Append ( @"
749+ if (" ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( @".IsSet)
750+ {
751+ return " ) . AppendEscaped ( currentBaseType . ArgumentName ) . Append ( @".Value;
752+ }" ) ;
753+ }
754+
755+ currentBaseType = currentBaseType . BaseType ;
756+ }
757+ }
758+
759+ private sealed record TypeMember (
655760 RegularUnionTypeMemberState State ,
656761 string ArgumentName ,
762+ TypeMember ? BaseType ,
657763 List < TypeMember > DerivedTypes ) ;
658764
659765 private class TypeMembersEqualityComparer : IEqualityComparer < IReadOnlyList < TypeMember > >
0 commit comments