Skip to content

Commit 988709b

Browse files
committed
Refactor
Mapper example WIP
1 parent 15b61ca commit 988709b

12 files changed

Lines changed: 101 additions & 18 deletions

MattSourceGenHelpers.Abstractions/Generator.cs renamed to MattSourceGenHelpers.Abstractions/Generate.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace MattSourceGenHelpers.Abstractions;
22

3-
public static class Generator
3+
public static class Generate
44
{
55
public static IGeneratorsFactory CurrentGenerator { get; set; } = new RecordingGeneratorsFactory();
66

MattSourceGenHelpers.Abstractions/IMethodImplementationGeneratorSwitchBodyCase.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
public interface IMethodImplementationGeneratorSwitchBodyCase<TArg1, TReturnType>
44
{
5-
IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> CompileTimeBody(Func<TArg1, TReturnType> func);
6-
IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> RuntimeBody(Func<TArg1, Action<TReturnType>> func);
5+
/// <summary>
6+
/// Specify case(s) will return a constant value.
7+
/// </summary>
8+
/// <param name="constantValueFactory">During code generation, this delegate will be ran to calculate the constant value.
9+
/// The delegate will not be used in the generated code. Only the value it produces after it's executed during code generation.</param>
10+
IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> ReturnConstantValue(Func<TArg1, TReturnType> constantValueFactory);
11+
12+
/// <summary>
13+
/// Specific case(s) will use the body provided.
14+
/// </summary>
15+
/// <param name="body">During code generation this body will be emitted.</param>
16+
IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> UseBody(Func<TArg1, Action<TReturnType>> body);
717
}

MattSourceGenHelpers.Abstractions/IMethodImplementationGeneratorSwitchBodyDefaultCase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
public interface IMethodImplementationGeneratorSwitchBodyDefaultCase<TArg1, TReturnType> : IMethodImplementationGenerator
44
{
55
IMethodImplementationGenerator<TArg1, TReturnType> CompileTimeBody(Func<TArg1, TReturnType> func);
6-
IMethodImplementationGenerator<TArg1, TReturnType> RuntimeBody(Func<TArg1, Func<TReturnType>> func);
6+
IMethodImplementationGenerator<TArg1, TReturnType> WithBody(Func<TArg1, Func<TReturnType>> func);
77
}

MattSourceGenHelpers.Abstractions/RecordingGeneratorsFactory.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,18 @@ public RecordingMethodImplementationGeneratorSwitchBodyCase(SwitchBodyRecord rec
131131
_cases = cases;
132132
}
133133

134-
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> CompileTimeBody(Func<TArg1, TReturnType> func)
134+
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> ReturnConstantValue(Func<TArg1, TReturnType> constantValueFactory)
135135
{
136136
foreach (var caseValue in _cases)
137137
{
138-
var result = func(caseValue);
138+
var result = constantValueFactory(caseValue);
139139
_record.CaseKeys.Add((object)caseValue ?? throw new InvalidOperationException("Switch case value cannot be null"));
140140
_record.CaseValues.Add(result);
141141
}
142142
return new RecordingMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>(_record);
143143
}
144144

145-
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> RuntimeBody(Func<TArg1, Action<TReturnType>> func)
145+
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> UseBody(Func<TArg1, Action<TReturnType>> body)
146146
{
147147
foreach (var caseValue in _cases)
148148
{
@@ -169,7 +169,7 @@ public IMethodImplementationGenerator<TArg1, TReturnType> CompileTimeBody(Func<T
169169
return new RecordingMethodImplementationGenerator<TArg1, TReturnType>(_record);
170170
}
171171

172-
public IMethodImplementationGenerator<TArg1, TReturnType> RuntimeBody(Func<TArg1, Func<TReturnType>> func)
172+
public IMethodImplementationGenerator<TArg1, TReturnType> WithBody(Func<TArg1, Func<TReturnType>> func)
173173
{
174174
_record.HasDefaultCase = true;
175175
return new RecordingMethodImplementationGenerator<TArg1, TReturnType>(_record);
File renamed without changes.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using MattSourceGenHelpers.Abstractions;
2+
3+
namespace MattSourceGenHelpers.Examples;
4+
5+
public partial class ColorsClassFluent
6+
{
7+
public partial string GetAllColorsString();
8+
9+
[GeneratesMethod(nameof(GetAllColorsString))]
10+
static IMethodImplementationGenerator GetAllColorsString_Generator() =>
11+
Generate
12+
.MethodImplementation<string>()
13+
.WithBody(() => string.Join(", ", Enum.GetNames<ColorsEnum>()));
14+
}
15+
16+
/*
17+
This will generate the following method:
18+
19+
public string GetAllColorsString()
20+
{
21+
return "Red, Green, Blue";
22+
}
23+
*/
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// using MattSourceGenHelpers.Abstractions;
2+
//
3+
// namespace MattSourceGenHelpers.Examples;
4+
//
5+
// public enum FourLeggedAnimal
6+
// {
7+
// Dog, Cat, Lizard
8+
// }
9+
//
10+
// public enum MammalAnimal
11+
// {
12+
// Dog, Cat
13+
// }
14+
//
15+
// public static class MapperFluent
16+
// {
17+
// public static partial MammalAnimal MapToMammal(FourLeggedAnimal fourLeggedAnimal);
18+
//
19+
// [GeneratesMethod(nameof(MapToMammal))]
20+
// static IMethodImplementationGenerator MapToAnimal_Generator() =>
21+
// Generate
22+
// .Method().WithParameter<FourLeggedAnimal>().WithReturnType<MammalAnimal>()
23+
// .WithSwitchBody()
24+
// .ForCases(GetFourLeggedAnimalsThatHasMatchInMammalAnimal()).CompileTimeBody(fourLeggedAnimal => Enum.Parse<MammalAnimal>(fourLeggedAnimal.ToString(), true))
25+
// .ForDefaultCase().RuntimeBody(fourLeggedAnimal => () => throw new ArgumentException($"Cannot map {fourLeggedAnimal} to a MammalAnimal"));
26+
//
27+
// static FourLeggedAnimal[] GetFourLeggedAnimalsThatHasMatchInMammalAnimal() =>
28+
// Enum
29+
// .GetValues<FourLeggedAnimal>()
30+
// .Where(fourLeggedAnimal => Enum.TryParse(typeof(MammalAnimal), fourLeggedAnimal.ToString(), true, out _))
31+
// .ToArray();
32+
// }
33+
//
34+
// /*
35+
// This will generate the following method:
36+
//
37+
// public static Animal MapToAnimal(FourLeggedAnimal fourLeggedAnimal);
38+
// {
39+
// switch (fourLeggedAnimal)
40+
// {
41+
// case FourLeggedAnimal.Dog: return MammalAnimal.Dog;
42+
// case FourLeggedAnimal.Cat: return MammalAnimal.Cat;
43+
// default: throw new ArgumentException($"Cannot map {fourLeggedAnimal} to a MammalAnimal");
44+
// }
45+
// }
46+
// */

MattSourceGenHelpers.Examples/PiExampleFluent.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ public static partial class PiExampleFluent
99

1010
[GeneratesMethod(nameof(GetPiDecimal))]
1111
static IMethodImplementationGenerator GetPiDecimal_Generator_Specialized() =>
12-
Generator
12+
Generate
1313
.MethodImplementation<int, int>()
1414
.WithSwitchBody()
15-
.ForCases(0, 1, 2, Integer.Range(300, 303)).CompileTimeBody(decimalNumber => SlowMath.CalculatePiDecimal(decimalNumber))
16-
.ForDefaultCase().RuntimeBody(decimalNumber => () => SlowMath.CalculatePiDecimal(decimalNumber));
15+
.ForCases(0, 1, 2, Integer.Range(300, 303)).ReturnConstantValue(decimalNumber => SlowMath.CalculatePiDecimal(decimalNumber))
16+
.ForDefaultCase().WithBody(decimalNumber => () => SlowMath.CalculatePiDecimal(decimalNumber));
1717
}
1818

1919
/*

MattSourceGenHelpers.Generators/GeneratesMethodGenerator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ private static string GenerateFromFluent(
291291

292292
var cases = record!;
293293

294-
// Extract default expression from the RuntimeBody or CompileTimeBody call in the method syntax
294+
// Extract default expression from the UseBody or ReturnConstantValue call in the method syntax
295295
string? defaultExpression = null;
296296
if (cases.HasDefaultCase)
297297
defaultExpression = ExtractDefaultExpressionFromFluentMethod(methodInfo.Syntax);
@@ -300,19 +300,19 @@ private static string GenerateFromFluent(
300300
}
301301

302302
/// <summary>
303-
/// Finds RuntimeBody(...) or CompileTimeBody(...) in the ForDefaultCase() chain
303+
/// Finds UseBody(...) or ReturnConstantValue(...) in the ForDefaultCase() chain
304304
/// and extracts the innermost lambda body expression string.
305305
/// </summary>
306306
private static string? ExtractDefaultExpressionFromFluentMethod(MethodDeclarationSyntax method)
307307
{
308-
// Walk all InvocationExpressionSyntax nodes; find the one named RuntimeBody or CompileTimeBody
308+
// Walk all InvocationExpressionSyntax nodes; find the one named UseBody or ReturnConstantValue
309309
// that follows a ForDefaultCase() call.
310310
var invocations = method.DescendantNodes().OfType<InvocationExpressionSyntax>();
311311
foreach (var inv in invocations)
312312
{
313313
if (inv.Expression is not MemberAccessExpressionSyntax ma) continue;
314314
var name = ma.Name.Identifier.Text;
315-
if (name is not ("RuntimeBody" or "CompileTimeBody")) continue;
315+
if (name is not ("UseBody" or "ReturnConstantValue")) continue;
316316

317317
var arg = inv.ArgumentList.Arguments.FirstOrDefault()?.Expression;
318318
return ExtractInnermostLambdaBody(arg);

MattSourceGenHelpers.Tests/PiExampleFluentTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ public static partial class TestPiFluentClass
5757

5858
[GeneratesMethod(nameof(GetPiDecimal))]
5959
static IMethodImplementationGenerator GetPiDecimal_Generator() =>
60-
Generator
60+
Generate
6161
.MethodImplementation<int, int>()
6262
.WithSwitchBody()
63-
.ForCases(0, 1, 2, Integer.Range(300, 303)).CompileTimeBody(decimalNumber => TestSlowMath.CalculatePiDecimal(decimalNumber))
64-
.ForDefaultCase().RuntimeBody(decimalNumber => () => TestSlowMath.CalculatePiDecimal(decimalNumber));
63+
.ForCases(0, 1, 2, Integer.Range(300, 303)).ReturnConstantValue(decimalNumber => TestSlowMath.CalculatePiDecimal(decimalNumber))
64+
.ForDefaultCase().WithBody(decimalNumber => () => TestSlowMath.CalculatePiDecimal(decimalNumber));
6565
}

0 commit comments

Comments
 (0)