Skip to content

Commit 52bbaee

Browse files
committed
Isolate logic into types
1 parent e87895a commit 52bbaee

11 files changed

Lines changed: 227 additions & 199 deletions

File tree

src/DynamoDBGenerator.SourceGenerator/Extensions/TypeExtensions.cs

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
using System.Collections;
21
using System.Collections.Concurrent;
3-
using System.Collections.Immutable;
4-
using System.Runtime.InteropServices;
52
using DynamoDBGenerator.SourceGenerator.Types;
63
using Microsoft.CodeAnalysis;
74

@@ -55,16 +52,6 @@ public static Func<ITypeSymbol, T> CacheFactory<T>(IEqualityComparer<ISymbol> co
5552
private static readonly Dictionary<ITypeSymbol, TypeIdentifier> TypeIdentifierDictionary =
5653
new(SymbolEqualityComparer.IncludeNullability);
5754

58-
public static bool IsNullable(this ITypeSymbol typeSymbol) => typeSymbol switch
59-
{
60-
{ IsReferenceType: true, NullableAnnotation: NullableAnnotation.None or NullableAnnotation.Annotated } => true,
61-
{ IsReferenceType: true, NullableAnnotation: NullableAnnotation.NotAnnotated } => false,
62-
{ IsValueType: true, OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } => true,
63-
{ IsValueType: true } => false,
64-
_ => throw new ArgumentOutOfRangeException(
65-
$"Could not determine nullablity of type '{typeSymbol.ToDisplayString()}'.")
66-
};
67-
6855
public static TypeIdentifier TypeIdentifier(this ITypeSymbol type)
6956
{
7057
if (TypeIdentifierDictionary.TryGetValue(type, out var typeIdentifier))
@@ -292,9 +279,9 @@ public static CodeFactory ToConversion(this IEnumerable<string> enumerable)
292279
return new CodeFactory(enumerable);
293280
}
294281

295-
public static CodeFactory ToConversion(this IEnumerable<string> enumerable, ITypeSymbol typeSymbol)
282+
public static CodeFactory ToConversion(this IEnumerable<string> enumerable, TypeIdentifier typeIdentifier)
296283
{
297-
return new CodeFactory(enumerable, new[] { typeSymbol });
284+
return new CodeFactory(enumerable, new[] { typeIdentifier });
298285
}
299286

300287
public static INamedTypeSymbol? TryGetNullableValueType(this ITypeSymbol type)
@@ -307,22 +294,6 @@ public static CodeFactory ToConversion(this IEnumerable<string> enumerable, ITyp
307294
: null;
308295
}
309296

310-
public static bool IsNumeric(this ITypeSymbol typeSymbol)
311-
{
312-
return typeSymbol.SpecialType
313-
is SpecialType.System_Int16
314-
or SpecialType.System_Byte
315-
or SpecialType.System_Int32
316-
or SpecialType.System_Int64
317-
or SpecialType.System_SByte
318-
or SpecialType.System_UInt16
319-
or SpecialType.System_UInt32
320-
or SpecialType.System_UInt64
321-
or SpecialType.System_Decimal
322-
or SpecialType.System_Double
323-
or SpecialType.System_Single;
324-
}
325-
326297
public static DynamoDbDataMember[] GetDynamoDbProperties(this ITypeSymbol symbol)
327298
{
328299
// A special rule when it comes to Tuples.

src/DynamoDBGenerator.SourceGenerator/Generations/AttributeExpressionName.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ internal static IEnumerable<string> CreateClasses(DynamoDBMarshallerArguments[]
2121
Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
2222
{
2323
// Using _comparer can double classes when there's a None nullable property mixed with a nullable property
24-
var hashSet = new HashSet<ITypeSymbol>(SymbolEqualityComparer.Default);
24+
var hashSet = new HashSet<TypeIdentifier>(TypeIdentifier.Default);
2525

2626
return arguments
2727
.SelectMany(x =>
@@ -105,26 +105,25 @@ private static IEnumerable<string> YieldSelector(
105105
.CreateScope($"yield return {camelCase};");
106106
}
107107

108-
private static CodeFactory CreateStruct(ITypeSymbol typeSymbol, Func<ITypeSymbol, DynamoDbDataMember[]> fn,
108+
private static CodeFactory CreateStruct(TypeIdentifier typeIdentifier, Func<ITypeSymbol, DynamoDbDataMember[]> fn,
109109
MarshallerOptions options)
110110
{
111-
var dataMembers = fn(typeSymbol)
111+
var dataMembers = fn(typeIdentifier.TypeSymbol)
112112
.Select(x => (
113-
IsUnknown: !options.IsConvertable(x.DataMember.Type) &&
114-
x.DataMember.Type.TypeIdentifier() is UnknownType,
113+
IsUnknown: options.IsUnknown(x.DataMember.TypeIdentifier),
115114
DDB: x,
116115
DbRef: $"#{x.AttributeName}",
117-
AttributeReference: TypeName(x.DataMember.Type),
116+
AttributeReference: TypeName(x.DataMember.TypeIdentifier.TypeSymbol),
118117
AttributeInterfaceName: AttributeExpressionNameTrackerInterface
119118
))
120119
.ToArray();
121120

122-
var structName = TypeName(typeSymbol);
121+
var structName = TypeName(typeIdentifier.TypeSymbol);
123122

124123
var @class =
125124
$"public readonly struct {structName} : {AttributeExpressionNameTrackerInterface}".CreateScope(
126-
TypeContent(typeSymbol, dataMembers, structName));
127-
return new CodeFactory(@class, dataMembers.Where(x => x.IsUnknown).Select(x => x.DDB.DataMember.Type));
125+
TypeContent(typeIdentifier.TypeSymbol, dataMembers, structName));
126+
return new CodeFactory(@class, dataMembers.Where(x => x.IsUnknown).Select(x => x.DDB.DataMember.TypeIdentifier));
128127
}
129128

130129
[MethodImpl(MethodImplOptions.AggressiveInlining)]

src/DynamoDBGenerator.SourceGenerator/Generations/AttributeExpressionValue.cs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static class AttributeExpressionValue
2020
private const string ValueProvider = "valueIdProvider";
2121

2222
private static IEnumerable<string> TypeContents(
23-
ITypeSymbol typeSymbol,
23+
TypeIdentifier typeIdentifier,
2424
(bool IsUnknown, DynamoDbDataMember DDB, string AttributeReference, string AttributeInterfaceName)[]
2525
dataMembers,
2626
string structName,
@@ -61,11 +61,11 @@ MarshallerOptions options
6161

6262
const string param = "entity";
6363

64-
var yields = (typeSymbol switch
64+
var yields = (typeIdentifier switch
6565
{
66-
_ when typeSymbol.IsNullable() => $"if ({param} is null)".CreateScope(
66+
{IsNullable:true} => $"if ({param} is null)".CreateScope(
6767
$"yield return new ({self}.Value, {AttributeValueUtilityFactory.Null});", "yield break;"),
68-
{ IsReferenceType: true } => $"if ({param} is null)".CreateScope(
68+
{ TypeSymbol.IsReferenceType: true } => $"if ({param} is null)".CreateScope(
6969
$"throw {ExceptionHelper.NullExceptionMethod}(\"{structName}\");"),
7070
_ => Enumerable.Empty<string>()
7171
})
@@ -74,12 +74,12 @@ _ when typeSymbol.IsNullable() => $"if ({param} is null)".CreateScope(
7474
.Concat(
7575
$"if ({self}.IsValueCreated)"
7676
.CreateScope(
77-
$"yield return new ({self}.Value, {Marshaller.InvokeMarshallerMethod(typeSymbol, "entity", $"\"{structName}\"", options, MarshallerOptions.FieldReference)}{HandeNullability(typeSymbol)});"
77+
$"yield return new ({self}.Value, {Marshaller.InvokeMarshallerMethod(typeIdentifier, "entity", $"\"{structName}\"", options, MarshallerOptions.FieldReference)}{HandeNullability(typeIdentifier)});"
7878
)
7979
)
8080
)
8181
.ScopeTo(
82-
$"IEnumerable<KeyValuePair<string, AttributeValue>> {interfaceName}.{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerAccessedValues}({typeSymbol.Representation().annotated} entity)");
82+
$"IEnumerable<KeyValuePair<string, AttributeValue>> {interfaceName}.{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerAccessedValues}({typeIdentifier.AnnotatedRepresenation} entity)");
8383

8484

8585
foreach (var yield in yields)
@@ -88,8 +88,8 @@ _ when typeSymbol.IsNullable() => $"if ({param} is null)".CreateScope(
8888
yield return $"public override string ToString() => {self}.Value;";
8989
}
9090

91-
private static string? HandeNullability(ITypeSymbol typeSymbol) =>
92-
typeSymbol.IsNullable() ? $" ?? {AttributeValueUtilityFactory.Null}" : null;
91+
private static string? HandeNullability(TypeIdentifier typeSymbol) =>
92+
typeSymbol.IsNullable ? $" ?? {AttributeValueUtilityFactory.Null}" : null;
9393

9494
private static IEnumerable<string> YieldSelector(
9595
(bool IsUnknown, DynamoDbDataMember DDB, string AttributeReference, string AttributeInterfaceName) x,
@@ -99,7 +99,7 @@ private static IEnumerable<string> YieldSelector(
9999

100100
if (x.IsUnknown)
101101
{
102-
return x.DDB.DataMember.Type.NotNullIfStatement(
102+
return x.DDB.DataMember.TypeIdentifier.TypeSymbol.NotNullIfStatement(
103103
accessPattern,
104104
$"foreach (var x in ({x.DDB.DataMember.Name} as {x.AttributeInterfaceName}).{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerAccessedValues}({accessPattern}))"
105105
.CreateScope("yield return x;")
@@ -109,54 +109,50 @@ private static IEnumerable<string> YieldSelector(
109109

110110

111111
return $"if ({x.DDB.DataMember.NameAsPrivateField}.IsValueCreated)".CreateScope(
112-
x.DDB.DataMember.Type.NotNullIfStatement(
112+
x.DDB.DataMember.TypeIdentifier.TypeSymbol.NotNullIfStatement(
113113
accessPattern,
114-
$"yield return new ({x.DDB.DataMember.NameAsPrivateField}.Value, {Marshaller.InvokeMarshallerMethod(x.DDB.DataMember.Type, $"entity.{x.DDB.DataMember.Name}", $"\"{x.DDB.DataMember.Name}\"", options, MarshallerOptions.FieldReference)}{HandeNullability(x.DDB.DataMember.Type)});"
114+
$"yield return new ({x.DDB.DataMember.NameAsPrivateField}.Value, {Marshaller.InvokeMarshallerMethod(x.DDB.DataMember.TypeIdentifier, $"entity.{x.DDB.DataMember.Name}", $"\"{x.DDB.DataMember.Name}\"", options, MarshallerOptions.FieldReference)}{HandeNullability(x.DDB.DataMember.TypeIdentifier)});"
115115
));
116116
}
117117

118118
internal static IEnumerable<string> CreateClasses(DynamoDBMarshallerArguments[] arguments,
119119
Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
120120
{
121121
// Using _comparer can double classes when there's a None nullable property mixed with a nullable property
122-
var hashSet = new HashSet<ITypeSymbol>(SymbolEqualityComparer.Default);
122+
var hashSet = new HashSet<TypeIdentifier>(TypeIdentifier.Default);
123123

124124
return arguments
125125
.SelectMany(x =>
126126
CodeFactory.Create(x.ArgumentType, y => CreateStruct(y, getDynamoDbProperties, options), hashSet));
127127
}
128128

129-
private static CodeFactory CreateStruct(ITypeSymbol typeSymbol, Func<ITypeSymbol, DynamoDbDataMember[]> fn,
129+
private static CodeFactory CreateStruct(TypeIdentifier typeIdentifier, Func<ITypeSymbol, DynamoDbDataMember[]> fn,
130130
MarshallerOptions options)
131131
{
132132
var dataMembers =
133-
options.IsConvertable(typeSymbol)
133+
options.IsConvertable(typeIdentifier.TypeSymbol)
134134
? Array
135135
.Empty<(bool IsUnknown, DynamoDbDataMember DDB, string AttributeReference, string
136136
AttributeInterfaceName)>()
137-
: fn(typeSymbol)
138-
.Select(x =>
139-
{
140-
return (
141-
IsUnknown: !options.IsConvertable(x.DataMember.Type) &&
142-
x.DataMember.Type.TypeIdentifier() is UnknownType,
143-
DDB: x,
144-
AttributeReference: TypeName(x.DataMember.Type),
145-
AttributeInterfaceName:
146-
$"{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerInterface}<{x.DataMember.Type.Representation().annotated}>"
147-
);
148-
})
137+
: fn(typeIdentifier.TypeSymbol)
138+
.Select(x => (
139+
IsUnknown: options.IsUnknown(x.DataMember.TypeIdentifier),
140+
DDB: x,
141+
AttributeReference: TypeName(x.DataMember.TypeIdentifier.TypeSymbol),
142+
AttributeInterfaceName:
143+
$"{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerInterface}<{x.DataMember.TypeIdentifier.AnnotatedRepresenation}>"
144+
))
149145
.ToArray();
150146

151-
var structName = TypeName(typeSymbol);
147+
var structName = TypeName(typeIdentifier.TypeSymbol);
152148
var interfaceName =
153-
$"{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerInterface}<{typeSymbol.Representation().annotated}>";
149+
$"{Constants.DynamoDBGenerator.Marshaller.AttributeExpressionValueTrackerInterface}<{typeIdentifier.AnnotatedRepresenation}>";
154150

155151
var @struct =
156-
$"public readonly struct {structName} : {interfaceName}".CreateScope(TypeContents(typeSymbol, dataMembers,
152+
$"public readonly struct {structName} : {interfaceName}".CreateScope(TypeContents(typeIdentifier, dataMembers,
157153
structName, interfaceName, options));
158154

159-
return new CodeFactory(@struct, dataMembers.Where(x => x.IsUnknown).Select(x => x.DDB.DataMember.Type));
155+
return new CodeFactory(@struct, dataMembers.Where(x => x.IsUnknown).Select(x => x.DDB.DataMember.TypeIdentifier));
160156
}
161157

162158
[MethodImpl(MethodImplOptions.AggressiveInlining)]

src/DynamoDBGenerator.SourceGenerator/Generations/Marshalling/Keys.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ private static IEnumerable<string> CreateAssignment(string validateReference, st
2323
DynamoDbDataMember dataMember, MarshallerOptions options)
2424
{
2525
const string reference = "value";
26-
var expectedType = dataMember.DataMember.Type.Representation().original;
27-
var expression = $"{keyReference} is {expectedType} {{ }} {reference}";
26+
var expression = $"{keyReference} is {dataMember.DataMember.TypeIdentifier.OriginalRepresenation} {{ }} {reference}";
2827

2928
var innerContent = $"if ({expression}) "
3029
.CreateScope(
31-
$@"{DictionaryName}.Add(""{dataMember.AttributeName}"", {InvokeMarshallerMethod(dataMember.DataMember.Type, reference, $"nameof({keyReference})", options)});")
30+
$@"{DictionaryName}.Add(""{dataMember.AttributeName}"", {InvokeMarshallerMethod(dataMember.DataMember.TypeIdentifier, reference, $"nameof({keyReference})", options)});")
3231
.Concat($"else if ({keyReference} is null) ".CreateScope(
3332
$@"throw {ExceptionHelper.KeysArgumentNullExceptionMethod}(""{dataMember.DataMember.Name}"", ""{keyReference}"");"))
3433
.Concat("else".CreateScope(
35-
$@"throw {ExceptionHelper.KeysInvalidConversionExceptionMethod}(""{dataMember.DataMember.Name}"", ""{keyReference}"", {keyReference}, ""{expectedType}"");"));
34+
$@"throw {ExceptionHelper.KeysInvalidConversionExceptionMethod}(""{dataMember.DataMember.Name}"", ""{keyReference}"", {keyReference}, ""{dataMember.DataMember.TypeIdentifier.OriginalRepresenation}"");"));
3635

3736
return $"if ({validateReference})".CreateScope(innerContent);
3837
}
@@ -76,7 +75,7 @@ private static IEnumerable<string> MethodBody(ITypeSymbol typeSymbol,
7675
internal static IEnumerable<string> CreateKeys(IEnumerable<DynamoDBMarshallerArguments> arguments,
7776
Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
7877
{
79-
var hashSet = new HashSet<ITypeSymbol>(SymbolEqualityComparer.IncludeNullability);
78+
var hashSet = new HashSet<TypeIdentifier>(TypeIdentifier.Nullable);
8079

8180
return arguments
8281
.SelectMany(x => CodeFactory.Create(x.EntityTypeSymbol,
@@ -148,12 +147,12 @@ internal static string AssignmentRoot(ITypeSymbol typeSymbol)
148147
$"new {KeyMarshallerImplementationTypeName}((pk, rk, ipk, irk, dm) => {ClassName}.{MethodName(typeSymbol)}({MarshallerOptions.FieldReference}, pk, rk, ipk, irk, dm))";
149148
}
150149

151-
private static CodeFactory StaticAttributeValueDictionaryKeys(ITypeSymbol typeSymbol,
150+
private static CodeFactory StaticAttributeValueDictionaryKeys(TypeIdentifier typeIdentifier,
152151
Func<ITypeSymbol, DynamoDbDataMember[]> fn, MarshallerOptions options)
153152
{
154153
var code =
155-
$"public static Dictionary<string, AttributeValue> {MethodName(typeSymbol)}({options.FullName} {MarshallerOptions.ParamReference}, object? {PkReference}, object? {RkReference}, bool {EnforcePkReference}, bool {EnforceRkReference}, string? index = null)"
156-
.CreateScope(MethodBody(typeSymbol, fn, options));
154+
$"public static Dictionary<string, AttributeValue> {MethodName(typeIdentifier.TypeSymbol)}({options.FullName} {MarshallerOptions.ParamReference}, object? {PkReference}, object? {RkReference}, bool {EnforcePkReference}, bool {EnforceRkReference}, string? index = null)"
155+
.CreateScope(MethodBody(typeIdentifier.TypeSymbol, fn, options));
157156

158157
return new CodeFactory(code);
159158
}

0 commit comments

Comments
 (0)