Skip to content

Commit d1138c5

Browse files
committed
[Regular Unions] Partial overloads prefer callbacks for base types over default
1 parent 674d42c commit d1138c5

7 files changed

Lines changed: 1068 additions & 122 deletions

File tree

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/RegularUnions/RegularUnionCodeGenerator.cs

Lines changed: 133 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)