Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions MattSourceGenHelpers.Abstractions/Generate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,44 @@ public static class Generate
{
public static IGeneratorsFactory CurrentGenerator { get; set; } = new RecordingGeneratorsFactory();

public static IMethodImplementationGenerator MethodImplementation() => CurrentGenerator.CreateImplementation();
public static IMethodImplementationGenerator<TReturnType> MethodImplementation<TReturnType>() => CurrentGenerator.CreateImplementation<TReturnType>();
public static IMethodImplementationGenerator<TArg1, TReturnType> MethodImplementation<TArg1, TReturnType>() => CurrentGenerator.CreateImplementation<TArg1, TReturnType>();
public static IMethodBuilder Method() => new MethodBuilder(CurrentGenerator);
}

public interface IMethodBuilder
{
IMethodBuilder<TArg1> WithParameter<TArg1>();
IMethodImplementationGenerator<TReturnType> WithReturnType<TReturnType>();
}
Comment on lines +7 to +14

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Generate.Method().WithReturnType<TReturnType>() (no-parameter) path is part of the new fluent entrypoint, but current tests only exercise the .WithParameter<TArg1>().WithReturnType<TReturnType>() chain. Adding at least one test that uses the parameterless chain (similar to ColorsClassFluent) would help catch regressions in this new API surface.

Copilot uses AI. Check for mistakes.

public interface IMethodBuilder<TArg1>
{
IMethodImplementationGenerator<TArg1, TReturnType> WithReturnType<TReturnType>();
}

public class MethodBuilder : IMethodBuilder
{
private readonly IGeneratorsFactory _generatorsFactory;

public MethodBuilder(IGeneratorsFactory generatorsFactory)
{
_generatorsFactory = generatorsFactory;
}

public IMethodBuilder<TArg1> WithParameter<TArg1>() => new MethodBuilder<TArg1>(_generatorsFactory);

public IMethodImplementationGenerator<TReturnType> WithReturnType<TReturnType>() => _generatorsFactory.CreateImplementation<TReturnType>();
}

public class MethodBuilder<TArg1> : IMethodBuilder<TArg1>
{
private readonly IGeneratorsFactory _generatorsFactory;

public MethodBuilder(IGeneratorsFactory generatorsFactory)
{
_generatorsFactory = generatorsFactory;
}

public IMethodImplementationGenerator<TArg1, TReturnType> WithReturnType<TReturnType>() => _generatorsFactory.CreateImplementation<TArg1, TReturnType>();
}
Comment on lines +21 to 45

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MethodBuilder / MethodBuilder<TArg1> are only constructed internally via Generate.Method() and are not referenced elsewhere in the repo. Consider making these concrete builder types internal (and potentially sealed) to avoid expanding the public API surface unnecessarily; consumers can still program against the public IMethodBuilder interfaces returned by Generate.Method().

Copilot uses AI. Check for mistakes.

public class EmptyGeneratorsFactory : IGeneratorsFactory
Expand Down Expand Up @@ -40,4 +75,4 @@ public interface IGeneratorsFactory
IMethodImplementationGenerator CreateImplementation();
IMethodImplementationGenerator<TReturnType> CreateImplementation<TReturnType>();
IMethodImplementationGenerator<TArg1, TReturnType> CreateImplementation<TArg1, TReturnType>();
}
}
4 changes: 2 additions & 2 deletions MattSourceGenHelpers.Examples/ColorsClassFluent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public partial class ColorsClassFluent
[GeneratesMethod(nameof(GetAllColorsString))]
static IMethodImplementationGenerator GetAllColorsString_Generator() =>
Generate
.MethodImplementation<string>()
.Method().WithReturnType<string>()
.WithBody(() => string.Join(", ", Enum.GetNames<ColorsEnum>()));
}

Expand All @@ -20,4 +20,4 @@ public string GetAllColorsString()
{
return "Red, Green, Blue";
}
*/
*/
4 changes: 2 additions & 2 deletions MattSourceGenHelpers.Examples/PiExampleFluent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static partial class PiExampleFluent
[GeneratesMethod(nameof(GetPiDecimal))]
static IMethodImplementationGenerator GetPiDecimal_Generator_Specialized() =>
Generate
.MethodImplementation<int, int>()
.Method().WithParameter<int>().WithReturnType<int>()
.WithSwitchBody()
.ForCases(0, 1, 2, Integer.Range(300, 303)).ReturnConstantValue(decimalNumber => SlowMath.CalculatePiDecimal(decimalNumber))
.ForDefaultCase().WithBody(decimalNumber => () => SlowMath.CalculatePiDecimal(decimalNumber));
Expand All @@ -32,4 +32,4 @@ public static int GetPiDecimal(int decimalNumber)
default: return CalculatePiDecimal(decimalNumber);
}
}
*/
*/
50 changes: 49 additions & 1 deletion MattSourceGenHelpers.Tests/PiExampleFluentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,40 @@ public static partial int GetPiDecimal(int decimalNumber)

Assert.That(generatedCode, Is.EqualTo(expectedCode));
}

[TestCase(1, "Dog")]
[TestCase(2, "Cat")]
[TestCase(3, "Unknown")]
public void MapperFluentLikeGenerator_ProducesExpectedRuntimeOutput(int source, string expected)
{
string result = TestMapperFluent.MapToMammal(source);

Assert.That(result, Is.EqualTo(expected));
}

[Test]
public void MapperFluentLikeGenerator_ProducesExpectedGeneratedCode()
{
string generatedCode = GeneratedCodeTestHelper.ReadGeneratedCode("TestMapperFluent_MapToMammal.g.cs");
string expectedCode = """
namespace MattSourceGenHelpers.Tests;

static partial class TestMapperFluent
{
public static partial string MapToMammal(int animalCode)
{
switch (animalCode)
{
case 1: return "Dog";
case 2: return "Cat";
default: return "Unknown";
}
}
}
""".ReplaceLineEndings("\n").TrimEnd();

Assert.That(generatedCode, Is.EqualTo(expectedCode));
}
}

public static partial class TestPiFluentClass
Expand All @@ -58,8 +92,22 @@ public static partial class TestPiFluentClass
[GeneratesMethod(nameof(GetPiDecimal))]
static IMethodImplementationGenerator GetPiDecimal_Generator() =>
Generate
.MethodImplementation<int, int>()
.Method().WithParameter<int>().WithReturnType<int>()
.WithSwitchBody()
.ForCases(0, 1, 2, Integer.Range(300, 303)).ReturnConstantValue(decimalNumber => TestSlowMath.CalculatePiDecimal(decimalNumber))
.ForDefaultCase().WithBody(decimalNumber => () => TestSlowMath.CalculatePiDecimal(decimalNumber));
}

public static partial class TestMapperFluent
{
public static partial string MapToMammal(int animalCode);

[GeneratesMethod(nameof(MapToMammal))]
static IMethodImplementationGenerator MapToMammal_Generator() =>
Generate
.Method().WithParameter<int>().WithReturnType<string>()
.WithSwitchBody()
.ForCases(1).ReturnConstantValue(_ => "Dog")
.ForCases(2).ReturnConstantValue(_ => "Cat")
.ForDefaultCase().WithBody(_ => () => "Unknown");
}