Skip to content

Commit 63d2645

Browse files
committed
Better member names for generic type parameters of an ad hoc union
1 parent 5867af1 commit 63d2645

15 files changed

Lines changed: 511 additions & 153 deletions

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/AdHocUnions/AdHocUnionCodeGenerator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private void GenerateImplicitConversions()
127127
{
128128
foreach (var memberType in _state.MemberTypes)
129129
{
130-
if (memberType.IsInterface || memberType.TypeDuplicateIndex is not null)
130+
if (memberType.IsInterface || memberType.TypeDuplicateCounter != 0)
131131
continue;
132132

133133
_sb.Append(@"
@@ -148,7 +148,7 @@ private void GenerateExplicitConversions()
148148
{
149149
foreach (var memberType in _state.MemberTypes)
150150
{
151-
if (memberType.IsInterface || memberType.TypeDuplicateIndex is not null)
151+
if (memberType.IsInterface || memberType.TypeDuplicateCounter != 0)
152152
continue;
153153

154154
_sb.Append(@"
@@ -811,10 +811,10 @@ private void GenerateConstructors()
811811
{
812812
var memberType = _state.MemberTypes[i];
813813

814-
if (memberType.TypeDuplicateIndex > 1)
814+
if (memberType.TypeDuplicateCounter > 1)
815815
continue;
816816

817-
var hasDuplicates = memberType.TypeDuplicateIndex is not null;
817+
var hasDuplicates = memberType.TypeDuplicateCounter != 0;
818818
var argName = hasDuplicates ? "value" : memberType.ArgumentName;
819819

820820
_sb.Append(@"
@@ -867,7 +867,7 @@ private void GenerateFactoriesForTypeDuplicates()
867867
{
868868
var memberType = _state.MemberTypes[i];
869869

870-
if (memberType.TypeDuplicateIndex is null)
870+
if (memberType.TypeDuplicateCounter == 0)
871871
continue;
872872

873873
_sb.Append(@"
@@ -892,7 +892,7 @@ private void GenerateMemberTypeFieldsAndProps()
892892
{
893893
var memberType = _state.MemberTypes[i];
894894

895-
if (memberType.TypeDuplicateIndex > 1)
895+
if (memberType.TypeDuplicateCounter > 1)
896896
continue;
897897

898898
_sb.Append(@"

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/AdHocUnions/AdHocUnionMemberTypeState.cs

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public sealed class AdHocUnionMemberTypeState : IEquatable<AdHocUnionMemberTypeS
1010
public bool IsNullableStruct { get; }
1111
public SpecialType SpecialType { get; }
1212
public bool IsInterface { get; }
13-
public int? TypeDuplicateIndex { get; }
13+
public int TypeDuplicateCounter { get; }
1414

1515
public string ArgumentName { get; }
1616
public string BackingFieldName { get; }
@@ -19,14 +19,14 @@ public sealed class AdHocUnionMemberTypeState : IEquatable<AdHocUnionMemberTypeS
1919
public AdHocUnionMemberTypeState(
2020
string name,
2121
string defaultName,
22-
int? typeDuplicateIndex,
22+
int typeDuplicateCounter,
2323
ITypedMemberState typeState,
2424
AdHocUnionMemberTypeSetting setting)
2525
{
2626
Name = name;
2727
ArgumentName = Name.MakeArgumentName();
28-
BackingFieldName = typeDuplicateIndex is null ? ArgumentName : defaultName.MakeArgumentName();
29-
TypeDuplicateIndex = typeDuplicateIndex;
28+
BackingFieldName = typeDuplicateCounter == 0 ? ArgumentName : defaultName.MakeArgumentName();
29+
TypeDuplicateCounter = typeDuplicateCounter;
3030
TypeFullyQualified = typeState.TypeFullyQualified;
3131
TypeMinimallyQualified = typeState.TypeMinimallyQualified;
3232
IsReferenceType = typeState.IsReferenceType;
@@ -37,32 +37,6 @@ public AdHocUnionMemberTypeState(
3737
Setting = setting;
3838
}
3939

40-
public static (string Name, string DefaultName) GetMemberName(
41-
AdHocUnionMemberTypeSetting setting,
42-
int? duplicateIndex,
43-
INamedTypeSymbol type,
44-
ITypedMemberState typeState)
45-
{
46-
var defaultName = typeState.IsNullableStruct
47-
? $"Nullable{type.TypeArguments[0].Name}"
48-
: type.Name;
49-
50-
var name = setting.Name ?? defaultName + duplicateIndex;
51-
52-
return (name, defaultName);
53-
}
54-
55-
public static (string Name, string DefaultName) GetMemberName(
56-
AdHocUnionMemberTypeSetting setting,
57-
int? duplicateIndex,
58-
IArrayTypeSymbol type)
59-
{
60-
var defaultName = $"{type.ElementType.Name}Array";
61-
var name = setting.Name ?? defaultName + duplicateIndex;
62-
63-
return (name, defaultName);
64-
}
65-
6640
public override bool Equals(object? obj)
6741
{
6842
return obj is AdHocUnionMemberTypeState other && Equals(other);
@@ -79,7 +53,7 @@ public bool Equals(AdHocUnionMemberTypeState? other)
7953
&& IsReferenceType == other.IsReferenceType
8054
&& SpecialType == other.SpecialType
8155
&& IsInterface == other.IsInterface
82-
&& TypeDuplicateIndex == other.TypeDuplicateIndex
56+
&& TypeDuplicateCounter == other.TypeDuplicateCounter
8357
&& Setting.Equals(other.Setting);
8458
}
8559

@@ -91,7 +65,7 @@ public override int GetHashCode()
9165
hashCode = (hashCode * 397) ^ IsReferenceType.GetHashCode();
9266
hashCode = (hashCode * 397) ^ (int)SpecialType;
9367
hashCode = (hashCode * 397) ^ IsInterface.GetHashCode();
94-
hashCode = (hashCode * 397) ^ TypeDuplicateIndex.GetHashCode();
68+
hashCode = (hashCode * 397) ^ TypeDuplicateCounter;
9569
hashCode = (hashCode * 397) ^ Setting.GetHashCode();
9670

9771
return hashCode;

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/AdHocUnions/AdHocUnionSourceGenerator.cs

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -158,51 +158,39 @@ private bool IsUnionCandidate(TypeDeclarationSyntax typeDeclaration)
158158
memberType = memberType.IsReferenceType && memberTypeSettings.IsNullableReferenceType ? memberType.WithNullableAnnotation(NullableAnnotation.Annotated) : memberType;
159159
var typeState = factory.Create(memberType);
160160

161-
var typeDuplicateIndex = 0;
161+
var typeDuplicateCounter = 0;
162162

163163
for (var j = 0; j < attributeType.TypeArguments.Length; j++)
164164
{
165165
if (j == i)
166166
{
167-
if (typeDuplicateIndex != 0)
168-
++typeDuplicateIndex;
167+
if (typeDuplicateCounter != 0)
168+
++typeDuplicateCounter;
169169

170170
continue;
171171
}
172172

173173
if (!SymbolEqualityComparer.Default.Equals(memberType, attributeType.TypeArguments[j]))
174174
continue;
175175

176-
if (j > i && typeDuplicateIndex != 0)
176+
if (j > i && typeDuplicateCounter != 0)
177177
break;
178178

179-
++typeDuplicateIndex;
179+
++typeDuplicateCounter;
180180
}
181181

182-
(string Name, string DefaultName) memberTypeName;
183-
var duplicateIndex = typeDuplicateIndex == 0 ? (int?)null : typeDuplicateIndex;
184-
185-
switch (memberType)
182+
if (!memberType.TryBuildMemberName(out var defaultName))
186183
{
187-
case INamedTypeSymbol namedTypeSymbol:
188-
memberTypeName = AdHocUnionMemberTypeState.GetMemberName(memberTypeSettings,
189-
duplicateIndex,
190-
namedTypeSymbol,
191-
typeState);
192-
break;
193-
case IArrayTypeSymbol arrayTypeSymbol:
194-
memberTypeName = AdHocUnionMemberTypeState.GetMemberName(memberTypeSettings,
195-
duplicateIndex,
196-
arrayTypeSymbol);
197-
break;
198-
default:
199-
Logger.LogError("Type of the member must be a named type or array type", tds);
200-
return null;
184+
Logger.LogError("Type of the member must be a named type or array type", tds);
185+
return null;
201186
}
202187

203-
memberTypeStates[i] = new AdHocUnionMemberTypeState(memberTypeName.Name,
204-
memberTypeName.DefaultName,
205-
duplicateIndex,
188+
var name = memberTypeSettings.Name ??
189+
(typeDuplicateCounter == 0 ? defaultName : defaultName + typeDuplicateCounter);
190+
191+
memberTypeStates[i] = new AdHocUnionMemberTypeState(name,
192+
defaultName,
193+
typeDuplicateCounter,
206194
typeState,
207195
memberTypeSettings);
208196
}

src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/TypeSymbolExtensions.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,4 +759,76 @@ public static bool HasRequiredMembers(this INamedTypeSymbol type)
759759

760760
return false;
761761
}
762+
763+
public static bool TryBuildMemberName(
764+
this INamedTypeSymbol type,
765+
[MaybeNullWhen(false)] out string name)
766+
{
767+
if (!type.IsGenericType)
768+
{
769+
name = type.Name;
770+
return true;
771+
}
772+
773+
var typeArguments = type.TypeArguments;
774+
775+
// Perf optimization
776+
if (typeArguments.Length == 1)
777+
{
778+
if (!typeArguments[0].TryBuildMemberName(out var typeArgumentName))
779+
{
780+
name = null;
781+
return false;
782+
}
783+
784+
name = $"{type.Name}Of{typeArgumentName}";
785+
return true;
786+
}
787+
788+
var typeArgumentNames = new string[typeArguments.Length];
789+
790+
for (var i = 0; i < typeArguments.Length; i++)
791+
{
792+
var typeArgument = typeArguments[i];
793+
794+
if (!typeArgument.TryBuildMemberName(out var typeArgumentName))
795+
{
796+
name = null;
797+
return false;
798+
}
799+
800+
typeArgumentNames[i] = typeArgumentName;
801+
}
802+
803+
name = $"{type.Name}Of{String.Join(String.Empty, typeArgumentNames)}";
804+
return true;
805+
}
806+
807+
public static bool TryBuildMemberName(
808+
this IArrayTypeSymbol type,
809+
[MaybeNullWhen(false)] out string name)
810+
{
811+
if (!type.ElementType.TryBuildMemberName(out var elementName))
812+
{
813+
name = null;
814+
return false;
815+
}
816+
817+
name = $"{elementName}Array";
818+
return true;
819+
}
820+
821+
public static bool TryBuildMemberName(
822+
this ITypeSymbol type,
823+
[MaybeNullWhen(false)] out string name)
824+
{
825+
name = null;
826+
827+
return type switch
828+
{
829+
IArrayTypeSymbol arrayTypeSymbol => TryBuildMemberName(arrayTypeSymbol, out name),
830+
INamedTypeSymbol namedTypeSymbol => TryBuildMemberName(namedTypeSymbol, out name),
831+
_ => false
832+
};
833+
}
762834
}

0 commit comments

Comments
 (0)