Skip to content

Commit 66f9ef3

Browse files
authored
Move keymarshalling method into marshaller class (#82)
1 parent 87fa129 commit 66f9ef3

File tree

5 files changed

+176
-135
lines changed

5 files changed

+176
-135
lines changed

src/DynamoDBGenerator.SourceGenerator/Generations/AttributeExpressionValue.cs

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using DynamoDBGenerator.SourceGenerator.Types;
44
using Microsoft.CodeAnalysis;
55
using static DynamoDBGenerator.SourceGenerator.Constants.DynamoDBGenerator;
6+
using Marshaller = DynamoDBGenerator.SourceGenerator.Generations.Marshalling.Marshaller;
7+
68
namespace DynamoDBGenerator.SourceGenerator.Generations;
79

810
public static class AttributeExpressionValue

src/DynamoDBGenerator.SourceGenerator/Generations/KeyMarshaller.cs

-123
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
using DynamoDBGenerator.SourceGenerator.Extensions;
2+
using DynamoDBGenerator.SourceGenerator.Types;
3+
using Microsoft.CodeAnalysis;
4+
using static DynamoDBGenerator.SourceGenerator.Constants.DynamoDBGenerator;
5+
6+
namespace DynamoDBGenerator.SourceGenerator.Generations.Marshalling;
7+
8+
internal static partial class Marshaller
9+
{
10+
internal static class KeyMarshaller
11+
{
12+
private const string DictionaryName = "attributeValues";
13+
private const string EnforcePkReference = "isPartitionKey";
14+
private const string EnforceRkReference = "isRangeKey";
15+
16+
private static readonly Func<ITypeSymbol, string> MethodName =
17+
TypeExtensions.SuffixedTypeSymbolNameFactory("Keys", SymbolEqualityComparer.IncludeNullability);
18+
19+
private const string PkReference = "partitionKey";
20+
private const string RkReference = "rangeKey";
21+
22+
private static IEnumerable<string> CreateAssignment(string validateReference, string keyReference,
23+
DynamoDbDataMember dataMember, MarshallerOptions options)
24+
{
25+
const string reference = "value";
26+
var expectedType = dataMember.DataMember.Type.Representation().original;
27+
var expression = $"{keyReference} is {expectedType} {{ }} {reference}";
28+
29+
var innerContent = $"if ({expression}) "
30+
.CreateScope(
31+
$@"{DictionaryName}.Add(""{dataMember.AttributeName}"", {InvokeMarshallerMethod(dataMember.DataMember.Type, reference, $"nameof({keyReference})", options)});")
32+
.Concat($"else if ({keyReference} is null) ".CreateScope(
33+
$@"throw {ExceptionHelper.KeysArgumentNullExceptionMethod}(""{dataMember.DataMember.Name}"", ""{keyReference}"");"))
34+
.Concat("else".CreateScope(
35+
$@"throw {ExceptionHelper.KeysInvalidConversionExceptionMethod}(""{dataMember.DataMember.Name}"", ""{keyReference}"", {keyReference}, ""{expectedType}"");"));
36+
37+
return $"if ({validateReference})".CreateScope(innerContent);
38+
}
39+
40+
private static IEnumerable<string> MethodBody(ITypeSymbol typeSymbol,
41+
Func<ITypeSymbol, DynamoDbDataMember[]> fn, MarshallerOptions options)
42+
{
43+
var keyStructure = DynamoDbDataMember.GetKeyStructure(fn(typeSymbol));
44+
if (keyStructure is null)
45+
{
46+
yield return @$"throw {ExceptionHelper.NoDynamoDBKeyAttributesExceptionMethod}(""{typeSymbol}"");";
47+
48+
yield break;
49+
}
50+
51+
yield return $"var {DictionaryName} = new Dictionary<string, AttributeValue>(2);";
52+
53+
var switchBody = GetAssignments(keyStructure.Value, options)
54+
.SelectMany(x =>
55+
$"case {(x.IndexName is null ? "null" : @$"""{x.IndexName}""")}:".CreateScope(x.assignments)
56+
.Append("break;"))
57+
.Append($"default: throw {ExceptionHelper.MissMatchedIndexNameExceptionMethod}(nameof(index), index);");
58+
59+
foreach (var s in "switch (index)".CreateScope(switchBody))
60+
yield return s;
61+
62+
var validateSwitch = $"if ({EnforcePkReference} && {EnforceRkReference} && {DictionaryName}.Count == 2)"
63+
.CreateScope($"return {DictionaryName};")
64+
.Concat($"if ({EnforcePkReference} && {EnforceRkReference} is false && {DictionaryName}.Count == 1)"
65+
.CreateScope($"return {DictionaryName};"))
66+
.Concat($"if ({EnforcePkReference} is false && {EnforceRkReference} && {DictionaryName}.Count == 1)"
67+
.CreateScope($"return {DictionaryName};"))
68+
.Concat($"if ({EnforcePkReference} && {EnforceRkReference} && {DictionaryName}.Count == 1)".CreateScope(
69+
$"throw {ExceptionHelper.KeysMissingDynamoDBAttributeExceptionMethod}({PkReference}, {RkReference});"))
70+
.Append($"throw {ExceptionHelper.ShouldNeverHappenExceptionMethod}();");
71+
72+
foreach (var s in validateSwitch)
73+
yield return s;
74+
}
75+
76+
internal static IEnumerable<string> CreateKeys(IEnumerable<DynamoDBMarshallerArguments> arguments,
77+
Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
78+
{
79+
var hashSet = new HashSet<ITypeSymbol>(SymbolEqualityComparer.IncludeNullability);
80+
81+
return arguments
82+
.SelectMany(x => CodeFactory.Create(x.EntityTypeSymbol,
83+
y => StaticAttributeValueDictionaryKeys(y, getDynamoDbProperties, options), hashSet));
84+
}
85+
86+
private static IEnumerable<(string? IndexName, IEnumerable<string> assignments)> GetAssignments(
87+
DynamoDBKeyStructure keyStructure, MarshallerOptions options)
88+
{
89+
yield return keyStructure switch
90+
{
91+
{ PartitionKey: var pk, SortKey: { } sortKey } => (null,
92+
CreateAssignment(EnforcePkReference, PkReference, pk, options)
93+
.Concat(CreateAssignment(EnforceRkReference, RkReference, sortKey, options))),
94+
{ PartitionKey: var pk, SortKey: null } => (null,
95+
CreateAssignment(EnforcePkReference, PkReference, pk, options)
96+
.Concat(MissingAssigment(EnforceRkReference, RkReference)))
97+
};
98+
99+
foreach (var gsi in keyStructure.GlobalSecondaryIndices)
100+
{
101+
yield return gsi switch
102+
{
103+
{ PartitionKey: var pk, SortKey: { } sortKey } => (gsi.Name,
104+
CreateAssignment(EnforcePkReference, PkReference, pk, options)
105+
.Concat(CreateAssignment(EnforceRkReference, RkReference, sortKey, options))),
106+
{ PartitionKey: var pk, SortKey: null } => (gsi.Name,
107+
CreateAssignment(EnforcePkReference, PkReference, pk, options)
108+
.Concat(MissingAssigment(EnforceRkReference, RkReference)))
109+
};
110+
}
111+
112+
foreach (var lsi in keyStructure.LocalSecondaryIndices)
113+
{
114+
yield return (lsi, keyStructure.PartitionKey) switch
115+
{
116+
{ PartitionKey: var pk, lsi: var sortKey } => (lsi.Name,
117+
CreateAssignment(EnforcePkReference, PkReference, pk, options)
118+
.Concat(CreateAssignment(EnforceRkReference, RkReference, sortKey.SortKey, options)))
119+
};
120+
}
121+
}
122+
123+
private static IEnumerable<string> MissingAssigment(string validateReference, string keyReference)
124+
{
125+
var expression = $"{validateReference} && {keyReference} is not null";
126+
return $"if ({expression})".CreateScope(
127+
$"throw {ExceptionHelper.KeysValueWithNoCorrespondenceMethod}(\"{keyReference}\", {keyReference});");
128+
}
129+
130+
internal static IEnumerable<string> IndexKeyMarshallerRootSignature(ITypeSymbol typeSymbol)
131+
{
132+
return
133+
$"public {Constants.DynamoDBGenerator.Marshaller.IndexKeyMarshallerInterface} IndexKeyMarshaller(string index)"
134+
.CreateScope(
135+
"ArgumentNullException.ThrowIfNull(index);",
136+
$"return new {IndexKeyMarshallerImplementationTypeName}((pk, rk, ipk, irk, dm) => {ClassName}.{MethodName(typeSymbol)}({MarshallerOptions.FieldReference}, pk, rk, ipk, irk, dm), index);"
137+
);
138+
}
139+
140+
public const string PrimaryKeyMarshallerReference = "PrimaryKeyMarshaller";
141+
142+
public const string PrimaryKeyMarshallerDeclaration =
143+
$"public {Constants.DynamoDBGenerator.Marshaller.KeyMarshallerInterface} {PrimaryKeyMarshallerReference} {{ get; }}";
144+
145+
internal static string AssignmentRoot(ITypeSymbol typeSymbol)
146+
{
147+
return
148+
$"new {KeyMarshallerImplementationTypeName}((pk, rk, ipk, irk, dm) => {ClassName}.{MethodName(typeSymbol)}({MarshallerOptions.FieldReference}, pk, rk, ipk, irk, dm))";
149+
}
150+
151+
private static CodeFactory StaticAttributeValueDictionaryKeys(ITypeSymbol typeSymbol,
152+
Func<ITypeSymbol, DynamoDbDataMember[]> fn, MarshallerOptions options)
153+
{
154+
var code =
155+
$"public static Dictionary<string, AttributeValue> {MethodName(typeSymbol)}({MarshallerOptions.Name} {MarshallerOptions.ParamReference}, object? {PkReference}, object? {RkReference}, bool {EnforcePkReference}, bool {EnforceRkReference}, string? index = null)"
156+
.CreateScope(MethodBody(typeSymbol, fn, options));
157+
158+
return new CodeFactory(code);
159+
}
160+
}
161+
}

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

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
using System.Collections.Immutable;
21
using DynamoDBGenerator.SourceGenerator.Extensions;
32
using DynamoDBGenerator.SourceGenerator.Types;
43
using Microsoft.CodeAnalysis;
54
using static DynamoDBGenerator.SourceGenerator.Constants.DynamoDBGenerator;
6-
namespace DynamoDBGenerator.SourceGenerator.Generations;
5+
namespace DynamoDBGenerator.SourceGenerator.Generations.Marshalling;
76

8-
public static class Marshaller
7+
internal static partial class Marshaller
98
{
109
private const string ClassName = $"_{Constants.DynamoDBGenerator.Marshaller.MarshallMethodName}_";
1110
private const string DataMember = "dataMember";
1211
private const string DictionaryReference = "attributeValues";
1312
private static readonly Func<ITypeSymbol, string> GetSerializationMethodName = TypeExtensions.SuffixedTypeSymbolNameFactory("_M", SymbolEqualityComparer.IncludeNullability);
1413
private const string ParamReference = "entity";
1514

16-
internal static IEnumerable<string> CreateClass(IEnumerable<DynamoDBMarshallerArguments> arguments, Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
15+
internal static IEnumerable<string> CreateClass(DynamoDBMarshallerArguments[] arguments, Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
1716
{
1817
return $"private static class {ClassName}".CreateScope(TypeContent(arguments, getDynamoDbProperties, options));
1918
}
@@ -59,7 +58,7 @@ private static CodeFactory CreateDictionaryMethod(ITypeSymbol typeSymbol, Func<I
5958

6059
}
6160

62-
private static IEnumerable<string> TypeContent(IEnumerable<DynamoDBMarshallerArguments> arguments, Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
61+
private static IEnumerable<string> TypeContent(DynamoDBMarshallerArguments[] arguments, Func<ITypeSymbol, DynamoDbDataMember[]> getDynamoDbProperties, MarshallerOptions options)
6362
{
6463
var hashset = new HashSet<ITypeSymbol>(SymbolEqualityComparer.IncludeNullability);
6564

@@ -69,8 +68,10 @@ private static IEnumerable<string> TypeContent(IEnumerable<DynamoDBMarshallerArg
6968
y => CreateMethod(y, getDynamoDbProperties, options),
7069
hashset
7170
)
72-
.Concat(CodeFactory.Create(x.ArgumentType, y => CreateMethod(y, getDynamoDbProperties, options), hashset))
73-
);
71+
.Concat(CodeFactory.Create(x.ArgumentType, y => CreateMethod(y, getDynamoDbProperties, options),
72+
hashset))
73+
)
74+
.Concat(KeyMarshaller.CreateKeys(arguments, getDynamoDbProperties, options));
7475
}
7576
private static CodeFactory CreateMethod(ITypeSymbol type, Func<ITypeSymbol, DynamoDbDataMember[]> fn, MarshallerOptions options)
7677
{

0 commit comments

Comments
 (0)