Skip to content

Commit 9f0e5a9

Browse files
committed
Merge branch 'main' into prepare-AWS-SDK-V4
2 parents 7100f5a + 2d97fb3 commit 9f0e5a9

23 files changed

Lines changed: 675 additions & 562 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ The source generator will look for attributes and implement interfaces that exis
5656
* `ValueTuple<T>` support: You don't have to declare your own types and could instead
5757
use [tuples](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples) with
5858
custom named fields that will act as if the tuple was a type with those data members.
59+
* Improved performance see [benchmark](./tests/DynamoDBGenerator.SourceGenerator.Benchmarks) project.
5960

6061
## Default conversion
6162

src/DynamoDBGenerator.SourceGenerator/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public static class Marshaller
8181
public static class AttributeValueUtilityFactory
8282
{
8383
private const string ClassName = "MarshallHelper";
84+
public const string ToAttributeValue = $"{ClassName}.ToAttributeValue";
8485
public const string Null = $"{ClassName}.Null";
8586
public const string ToList = $"{ClassName}.ToList";
8687
public const string ToArray = $"{ClassName}.ToArray";

src/DynamoDBGenerator.SourceGenerator/DynamoDBDMarshaller.cs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -78,47 +78,48 @@ private static (MarshallerOptions, IEnumerable<DynamoDBMarshallerArguments>) Cre
7878

7979
return (MarshallerOptions.Create(type, converter, enumStrategy), Arguments(attributes, type));
8080

81-
static IEnumerable<DynamoDBMarshallerArguments> Arguments(ImmutableArray<AttributeData> attributes, ISymbol type)
81+
static IEnumerable<DynamoDBMarshallerArguments> Arguments(
82+
ImmutableArray<AttributeData> attributes,
83+
ISymbol type)
8284
{
83-
var marshallerAttributes = attributes
85+
return attributes
8486
.Where(attributeData => attributeData.AttributeClass is
8587
{
8688
ContainingNamespace.Name: Constants.DynamoDBGenerator.Namespace.Attributes,
8789
Name: Constants.DynamoDBGenerator.Attribute.DynamoDBMarshaller,
8890
ContainingAssembly.Name: Constants.DynamoDBGenerator.AssemblyName
89-
});
90-
91-
foreach (var attributeData in marshallerAttributes)
92-
{
93-
var entityType = attributeData.NamedArguments
94-
.Where(x => x.Key is EntityType)
95-
.Cast<KeyValuePair<string, TypedConstant>?>()
96-
.FirstOrDefault() is { } entityType1
97-
? entityType1.Value is { Value: INamedTypeSymbol et }
98-
? et
99-
: throw new ArgumentException(
100-
$"Could not determine type conversion from argument '{entityType1.Key}'.")
101-
: type;
102-
103-
if (entityType is not INamedTypeSymbol entityTypeSymbol)
104-
throw new ArgumentException("Could not determine type conversion from attribute constructor.");
105-
106-
var propertyName = attributeData.NamedArguments.FirstOrDefault(x => x.Key is AccessName).Value;
107-
108-
yield return new DynamoDBMarshallerArguments(
109-
entityTypeSymbol,
110-
attributeData.NamedArguments
111-
.Where(x => x.Key is ArgumentType)
91+
})
92+
.Select(x =>
93+
{
94+
var entityType = x.NamedArguments
95+
.Where(x => x.Key is EntityType)
11296
.Cast<KeyValuePair<string, TypedConstant>?>()
113-
.FirstOrDefault() is { } argumentType
114-
? argumentType.Value is { Value: INamedTypeSymbol namedTypeSymbol }
115-
? namedTypeSymbol
97+
.FirstOrDefault() is { } entityType1
98+
? entityType1.Value is { Value: INamedTypeSymbol et }
99+
? et
116100
: throw new ArgumentException(
117-
$"Could not determine type conversion from argument '{argumentType.Key}'.")
118-
: null,
119-
propertyName.Value?.ToString()
120-
);
121-
}
101+
$"Could not determine type conversion from argument '{entityType1.Key}'.")
102+
: type;
103+
104+
if (entityType is not INamedTypeSymbol entityTypeSymbol)
105+
throw new ArgumentException("Could not determine type conversion from attribute constructor.");
106+
107+
var propertyName = x.NamedArguments.FirstOrDefault(y => y.Key is AccessName).Value;
108+
109+
return new DynamoDBMarshallerArguments(
110+
entityTypeSymbol,
111+
x.NamedArguments
112+
.Where(x => x.Key is ArgumentType)
113+
.Cast<KeyValuePair<string, TypedConstant>?>()
114+
.FirstOrDefault() is { } argumentType
115+
? argumentType.Value is { Value: INamedTypeSymbol namedTypeSymbol }
116+
? namedTypeSymbol
117+
: throw new ArgumentException(
118+
$"Could not determine type conversion from argument '{argumentType.Key}'.")
119+
: null,
120+
propertyName.Value?.ToString()
121+
);
122+
});
122123
}
123124
}
124125
}

src/DynamoDBGenerator.SourceGenerator/Extensions/CompilationExtensions.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
using System.Collections.Immutable;
22
using Microsoft.CodeAnalysis;
3-
using Microsoft.CodeAnalysis.CSharp.Syntax;
43

54
namespace DynamoDBGenerator.SourceGenerator.Extensions;
65

76
// Great source: https://github.com/dotnet/runtime/blob/main/src/tools/illink/src/ILLink.RoslynAnalyzer/CompilationExtensions.cs
87
public static class CompilationExtensions
98
{
10-
public static ReadOnlySpan<INamedTypeSymbol> GetTypeSymbols(this Compilation compilation, ImmutableArray<SyntaxNode> classDeclarations)
9+
public static ReadOnlySpan<INamedTypeSymbol> GetTypeSymbols(this Compilation compilation,
10+
ImmutableArray<SyntaxNode> classDeclarations)
1111
{
1212
var span = classDeclarations.AsSpan();
1313
var symbols = new INamedTypeSymbol[classDeclarations.Length];
@@ -19,7 +19,8 @@ public static ReadOnlySpan<INamedTypeSymbol> GetTypeSymbols(this Compilation com
1919
.GetSemanticModel(classDeclarationSyntax.SyntaxTree)
2020
.GetDeclaredSymbol(classDeclarationSyntax)
2121
is not INamedTypeSymbol typeSymbol)
22-
throw new ArgumentException($"Could not convert the '{classDeclarationSyntax.ToFullString()}' into a '{nameof(ITypeSymbol)}'.");
22+
throw new ArgumentException(
23+
$"Could not convert the '{classDeclarationSyntax.ToFullString()}' into a '{nameof(ITypeSymbol)}'.");
2324

2425
symbols[i] = typeSymbol;
2526
}

src/DynamoDBGenerator.SourceGenerator/Extensions/EnumerableExtensions.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@ public static IEnumerable<T> AllButLast<T>(this IEnumerable<T> enumerable, Func<
1616
buffer = item;
1717
}
1818

19-
if (isBuffered)
20-
{
21-
yield return buffer!;
22-
}
19+
if (isBuffered) yield return buffer!;
2320
}
24-
public static IEnumerable<TResult> AllAndLast<T, TResult>(this IEnumerable<T> enumerable, Func<T, TResult> @default, Func<T, TResult> onLast)
21+
22+
public static IEnumerable<TResult> AllAndLast<T, TResult>(this IEnumerable<T> enumerable, Func<T, TResult> @default,
23+
Func<T, TResult> onLast)
2524
{
2625
var buffer = default(T);
2726
var isBuffered = false;
@@ -35,10 +34,6 @@ public static IEnumerable<TResult> AllAndLast<T, TResult>(this IEnumerable<T> en
3534
buffer = item;
3635
}
3736

38-
if (isBuffered)
39-
{
40-
yield return onLast(buffer!);
41-
}
37+
if (isBuffered) yield return onLast(buffer!);
4238
}
43-
4439
}
Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using Microsoft.CodeAnalysis;
2+
23
namespace DynamoDBGenerator.SourceGenerator.Extensions;
34

45
public static class NotNullEvaluationExtensions
56
{
6-
public static string NotNullTernaryExpression(this ITypeSymbol typeSymbol, in string accessPattern, in string truthy,
7+
public static string NotNullTernaryExpression(this ITypeSymbol typeSymbol, in string accessPattern,
8+
in string truthy,
79
in string falsy)
810
{
911
var result = Expression(in typeSymbol, in accessPattern) is { } expression
@@ -18,47 +20,51 @@ private static string CreateException(in string accessPattern)
1820
return $"throw {Constants.DynamoDBGenerator.ExceptionHelper.NullExceptionMethod}(nameof({accessPattern}));";
1921
}
2022

21-
public static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbol, string accessPattern, string truthy)
23+
public static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbol, string accessPattern,
24+
string truthy)
2225
{
2326
return NotNullIfStatement(typeSymbol, accessPattern, obj: truthy);
2427
}
25-
public static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbol, string accessPattern, IEnumerable<string> truthy)
28+
29+
public static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbol, string accessPattern,
30+
IEnumerable<string> truthy)
2631
{
2732
return NotNullIfStatement(typeSymbol, accessPattern, obj: truthy);
2833
}
29-
34+
3035
private static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbol, string accessPattern, object obj)
3136
{
3237
if (Expression(typeSymbol, accessPattern) is not { } expression)
3338
{
34-
if(obj is string single)
35-
yield return single;
36-
else if(obj is IEnumerable<string> truthies)
37-
foreach (var x in truthies)
38-
yield return x;
39-
else
40-
throw new NotImplementedException($"Method '{nameof(NotNullIfStatement)}' could not determine type '{obj.GetType().Name}'");
39+
if (obj is string single)
40+
yield return single;
41+
else if (obj is IEnumerable<string> truthies)
42+
foreach (var x in truthies)
43+
yield return x;
44+
else
45+
throw new NotImplementedException(
46+
$"Method '{nameof(NotNullIfStatement)}' could not determine type '{obj.GetType().Name}'");
4147
}
4248
else
4349
{
44-
45-
var ifClause = obj switch
50+
var ifClause = obj switch
4651
{
47-
string single => $"if ({expression})".CreateScope(single),
48-
IEnumerable<string> multiple => $"if ({expression})".CreateScope(multiple),
49-
_ => throw new NotImplementedException($"Method '{nameof(NotNullIfStatement)}' could not determine type '{obj.GetType().Name}'")
52+
string single => $"if ({expression})".CreateScope(single),
53+
IEnumerable<string> multiple => $"if ({expression})".CreateScope(multiple),
54+
_ => throw new NotImplementedException(
55+
$"Method '{nameof(NotNullIfStatement)}' could not determine type '{obj.GetType().Name}'")
5056
};
5157
var enumerable = typeSymbol.NullableAnnotation switch
5258
{
5359
NullableAnnotation.None or NullableAnnotation.Annotated => ifClause,
54-
NullableAnnotation.NotAnnotated => ifClause.Concat("else".CreateScope(CreateException(in accessPattern))),
60+
NullableAnnotation.NotAnnotated => ifClause.Concat(
61+
"else".CreateScope(CreateException(in accessPattern))),
5562
_ => throw new ArgumentOutOfRangeException(typeSymbol.ToDisplayString())
5663
};
5764

5865
foreach (var element in enumerable)
5966
yield return element;
6067
}
61-
6268
}
6369

6470

@@ -73,7 +79,6 @@ private static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbo
7379

7480
static string? OnValueType(in ITypeSymbol typeSymbol, in string accessPattern)
7581
{
76-
7782
if (typeSymbol.TryGetNullableValueType() is not { } namedTypeSymbol)
7883
return null;
7984

@@ -86,6 +91,4 @@ private static IEnumerable<string> NotNullIfStatement(this ITypeSymbol typeSymbo
8691
: $"{accessPattern} is not null && {expression}";
8792
}
8893
}
89-
90-
91-
}
94+
}

src/DynamoDBGenerator.SourceGenerator/Extensions/StringExtensions.cs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,39 @@
1+
using System.Runtime.CompilerServices;
2+
13
namespace DynamoDBGenerator.SourceGenerator.Extensions;
24

35
public static class StringExtensions
46
{
5-
public static string ToCamelCaseFromPascal(this string str, [System.Runtime.CompilerServices.CallerMemberName] string? memberName = null)
7+
public static string ToCamelCaseFromPascal(this string str, [CallerMemberName] string? memberName = null)
68
{
79
return ToCamelCaseFromPascal(str.AsSpan(), memberName).ToString();
810
}
911

10-
public static string ToPrivateFieldFromPascal(this string str, [System.Runtime.CompilerServices.CallerMemberName] string? memberName = null)
12+
public static string ToPrivateFieldFromPascal(this string str, [CallerMemberName] string? memberName = null)
1113
{
1214
return ToPrivateFieldFromPascal(str.AsSpan(), memberName).ToString();
1315
}
1416

15-
public static ReadOnlySpan<char> ToPrivateFieldFromPascal(this ReadOnlySpan<char> span, [System.Runtime.CompilerServices.CallerMemberName] string? memberName = null)
17+
public static ReadOnlySpan<char> ToPrivateFieldFromPascal(this ReadOnlySpan<char> span,
18+
[CallerMemberName] string? memberName = null)
1619
{
1720
if (span.Length is 0)
1821
throw new ArgumentException($"Null or Empty string was provided from '{memberName}'");
1922

2023
var array = new char[span.Length + 1];
2124

2225
array[0] = '_';
23-
array[1] = Char.ToLowerInvariant(span[0]);
26+
array[1] = char.ToLowerInvariant(span[0]);
2427

2528
// Skip first element since we handled it manually.
2629
for (var i = 1; i < span.Length; i++)
2730
array[i + 1] = span[i];
2831

2932
return array;
3033
}
31-
public static ReadOnlySpan<char> ToCamelCaseFromPascal(this ReadOnlySpan<char> span, [System.Runtime.CompilerServices.CallerMemberName] string? memberName = null)
34+
35+
public static ReadOnlySpan<char> ToCamelCaseFromPascal(this ReadOnlySpan<char> span,
36+
[CallerMemberName] string? memberName = null)
3237
{
3338
if (span.Length is 0)
3439
throw new ArgumentException($"Null or Empty string was provided from '{memberName}'");
@@ -38,7 +43,7 @@ public static ReadOnlySpan<char> ToCamelCaseFromPascal(this ReadOnlySpan<char> s
3843

3944
var array = new char[span.Length];
4045

41-
array[0] = Char.ToLowerInvariant(span[0]);
46+
array[0] = char.ToLowerInvariant(span[0]);
4247

4348
// Skip first element since we handled it manually.
4449
for (var i = 1; i < span.Length; i++)
@@ -47,21 +52,13 @@ public static ReadOnlySpan<char> ToCamelCaseFromPascal(this ReadOnlySpan<char> s
4752
return array;
4853
}
4954

50-
public static IEnumerable<string> ScopeTo(this IEnumerable<string> content, string header)
51-
{
52-
return CreateScope(header, content);
53-
}
55+
public static IEnumerable<string> ScopeTo(this IEnumerable<string> content, string header) => CreateScope(header, content);
5456

55-
public static IEnumerable<string> CreateScope(this string header, IEnumerable<string> content)
56-
{
57-
yield return header;
58-
yield return "{";
59-
60-
foreach (var s in content)
61-
yield return $" {s}";
62-
63-
yield return "}";
64-
}
57+
public static IEnumerable<string> CreateScope(this string header, IEnumerable<string> content) => content
58+
.Select(x => $" {x}")
59+
.Prepend("{")
60+
.Prepend(header)
61+
.Append("}");
6562

6663
public static IEnumerable<string> CreateScope(this string header, string content)
6764
{
@@ -92,12 +89,9 @@ public static string ToAlphaNumericMethodName(this string txt)
9289
for (var i = 0; i < txt.Length; i++)
9390
{
9491
var c = txt[i];
95-
if (char.IsLetter(c) || index > 0 && char.IsNumber(c))
96-
{
97-
arr[index++] = c;
98-
}
92+
if (char.IsLetter(c) || (index > 0 && char.IsNumber(c))) arr[index++] = c;
9993
}
10094

10195
return new string(arr, 0, index);
10296
}
103-
}
97+
}

0 commit comments

Comments
 (0)