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
2 changes: 2 additions & 0 deletions MattSourceGenHelpers.Abstractions/Assembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MattSourceGenHelpers.Tests")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MattSourceGenHelpers.Generators")]
80 changes: 6 additions & 74 deletions MattSourceGenHelpers.Abstractions/Generate.cs
Original file line number Diff line number Diff line change
@@ -1,78 +1,10 @@
namespace MattSourceGenHelpers.Abstractions;
using JetBrains.Annotations;

public static class Generate
{
public static IGeneratorsFactory CurrentGenerator { get; set; } = new RecordingGeneratorsFactory();

public static IMethodBuilder Method() => new MethodBuilder(CurrentGenerator);
}

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

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>();
}
namespace MattSourceGenHelpers.Abstractions;

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>();
}

public class EmptyGeneratorsFactory : IGeneratorsFactory
{
public IMethodImplementationGenerator CreateImplementation() => new EmptyMethodImplementationGenerator();
public IMethodImplementationGenerator<TReturnType> CreateImplementation<TReturnType>() => new EmptyMethodImplementationGenerator<TReturnType>();
public IMethodImplementationGenerator<TArg1, TReturnType> CreateImplementation<TArg1, TReturnType>() => new EmptyMethodImplementationGenerator<TArg1, TReturnType>();
}

public class EmptyMethodImplementationGenerator : IMethodImplementationGenerator
{
public IMethodImplementationGenerator WithBody(Action body) => this;
public IMethodImplementationGenerator WithBody(Func<object> body) => this;
}

public class EmptyMethodImplementationGenerator<TReturnType> : IMethodImplementationGenerator<TReturnType>
{
public IMethodImplementationGenerator UseBody(Func<object> body) => this;
}

public class EmptyMethodImplementationGenerator<TArg1, TReturnType> : IMethodImplementationGenerator<TArg1, TReturnType>
public static class Generate
{
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> WithSwitchBody() =>
new RecordingMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>(new SwitchBodyRecord());
public IMethodImplementationGenerator WithBody(Action body) => this;
public IMethodImplementationGenerator WithBody(Func<object> body) => this;
}
internal static IGeneratorsFactory CurrentGenerator { get; [UsedImplicitly] set; } = new MockGeneratorsFactory();

public interface IGeneratorsFactory
{
IMethodImplementationGenerator CreateImplementation();
IMethodImplementationGenerator<TReturnType> CreateImplementation<TReturnType>();
IMethodImplementationGenerator<TArg1, TReturnType> CreateImplementation<TArg1, TReturnType>();
}
public static IMethodBuilder Method() => CurrentGenerator.ForMethod();
}
9 changes: 9 additions & 0 deletions MattSourceGenHelpers.Abstractions/IGeneratorsFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MattSourceGenHelpers.Abstractions;

public interface IGeneratorsFactory
{
IMethodBuilder ForMethod();

IMethodImplementationGenerator<TReturnType> CreateImplementation<TReturnType>();
IMethodImplementationGenerator<TArg1, TReturnType> CreateImplementation<TArg1, TReturnType>();
}
12 changes: 12 additions & 0 deletions MattSourceGenHelpers.Abstractions/IMethodBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace MattSourceGenHelpers.Abstractions;

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

public interface IMethodBuilder<TArg1>
{
IMethodImplementationGenerator<TArg1, TReturnType> WithReturnType<TReturnType>();
}
6 changes: 0 additions & 6 deletions MattSourceGenHelpers.Abstractions/IMethodGenerator.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
namespace MattSourceGenHelpers.Abstractions;
using JetBrains.Annotations;

public interface IMethodImplementationGenerator<TReturnType> : IMethodImplementationGenerator
namespace MattSourceGenHelpers.Abstractions;

public interface IMethodImplementationGenerator<[UsedImplicitly] TReturnType> : IMethodImplementationGenerator
{
IMethodImplementationGenerator UseBody(Func<object> body);
IMethodImplementationGenerator UseBody([UsedImplicitly] Func<object> body);
}

public interface IMethodImplementationGenerator<TArg1, TReturnType> : IMethodImplementationGenerator
{
IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> WithSwitchBody();
}

public interface IMethodImplementationGeneratorVoid
{
IMethodImplementationGenerator CompileTimeBody(Action func);
IMethodImplementationGenerator RuntimeBody(Action func);
}

public interface IMethodImplementationGenerator;
6 changes: 0 additions & 6 deletions MattSourceGenHelpers.Abstractions/Integer.cs

This file was deleted.

13 changes: 13 additions & 0 deletions MattSourceGenHelpers.Abstractions/MethodBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace MattSourceGenHelpers.Abstractions;

public class MethodBuilder(IGeneratorsFactory generatorsFactory) : IMethodBuilder
{
public IMethodBuilder<TArg1> WithParameter<TArg1>() => new MethodBuilder<TArg1>(generatorsFactory);

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

public class MethodBuilder<TArg1>(IGeneratorsFactory generatorsFactory) : IMethodBuilder<TArg1>
{
public IMethodImplementationGenerator<TArg1, TReturnType> WithReturnType<TReturnType>() => generatorsFactory.CreateImplementation<TArg1, TReturnType>();
}
68 changes: 68 additions & 0 deletions MattSourceGenHelpers.Abstractions/Mocks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
namespace MattSourceGenHelpers.Abstractions;

public class MockGeneratorsFactory : IGeneratorsFactory
{
public IMethodBuilder ForMethod() => new MockMethodBuilder();

public IMethodImplementationGenerator<TReturnType> CreateImplementation<TReturnType>() => new MockMethodImplementationGenerator<TReturnType>();

public IMethodImplementationGenerator<TArg1, TReturnType> CreateImplementation<TArg1, TReturnType>() =>
new MockMethodImplementationGenerator<TArg1, TReturnType>();
}

public class MockMethodImplementationGenerator<TReturnType> : IMethodImplementationGenerator<TReturnType>
{
public IMethodImplementationGenerator UseBody(Func<object> body) => this;
}

public class MockMethodImplementationGenerator<TArg1, TReturnType> : IMethodImplementationGenerator<TArg1, TReturnType>
{
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> WithSwitchBody() =>
new MockMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>();
}

public class MockMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> : IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>
{
public IMethodImplementationGeneratorSwitchBodyCase<TArg1, TReturnType> ForCases(params object[] cases)
=> new MockMethodImplementationGeneratorSwitchBodyCase<TArg1, TReturnType>();

public IMethodImplementationGeneratorSwitchBodyDefaultCase<TArg1, TReturnType> ForDefaultCase()
=> new MockMethodImplementationGeneratorSwitchBodyDefaultCase<TArg1, TReturnType>();
}

public class MockMethodImplementationGeneratorSwitchBodyDefaultCase<TArg1, TReturnType> : IMethodImplementationGeneratorSwitchBodyDefaultCase<TArg1,
TReturnType>
{
public IMethodImplementationGenerator<TArg1, TReturnType> ReturnConstantValue(Func<TArg1, TReturnType> func)
=> new MockMethodImplementationGenerator<TArg1, TReturnType>();

public IMethodImplementationGenerator<TArg1, TReturnType> UseBody(Func<TArg1, Func<TReturnType>> func)
=> new MockMethodImplementationGenerator<TArg1, TReturnType>();
}

public class MockMethodImplementationGeneratorSwitchBodyCase<TArg1, TReturnType> : IMethodImplementationGeneratorSwitchBodyCase<TArg1, TReturnType>
{
public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> ReturnConstantValue(Func<TArg1, TReturnType> constantValueFactory)
=> new MockMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>();

public IMethodImplementationGeneratorSwitchBody<TArg1, TReturnType> UseBody(Func<TArg1, Action<TReturnType>> body)
=> new MockMethodImplementationGeneratorSwitchBody<TArg1, TReturnType>();
}

public class MockMethodBuilder : IMethodBuilder
{
public IMethodBuilder<TArg1> WithParameter<TArg1>() => new MockMethodBuilder<TArg1>();

public IMethodImplementationGenerator<TReturnType> WithReturnType<TReturnType>() => new MockImplementationGenerator<TReturnType>();
}

public class MockImplementationGenerator<TReturnType> : IMethodImplementationGenerator<TReturnType>
{
public IMethodImplementationGenerator UseBody(Func<object> body) => this;
}

Comment on lines +56 to +63
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

There are two classes implementing IMethodImplementationGenerator<TReturnType> with nearly identical implementations but different names: MockMethodImplementationGenerator<TReturnType> (line 13) and MockImplementationGenerator<TReturnType> (line 59). The second is used by MockMethodBuilder.WithReturnType<TReturnType>() but could simply reuse MockMethodImplementationGenerator<TReturnType>, eliminating the duplication and inconsistent naming.

Suggested change
public IMethodImplementationGenerator<TReturnType> WithReturnType<TReturnType>() => new MockImplementationGenerator<TReturnType>();
}
public class MockImplementationGenerator<TReturnType> : IMethodImplementationGenerator<TReturnType>
{
public IMethodImplementationGenerator UseBody(Func<object> body) => this;
}
public IMethodImplementationGenerator<TReturnType> WithReturnType<TReturnType>() => new MockMethodImplementationGenerator<TReturnType>();
}

Copilot uses AI. Check for mistakes.
public class MockMethodBuilder<TArg1Input> : IMethodBuilder<TArg1Input>
{
public IMethodImplementationGenerator<TArg1Input, TReturnType> WithReturnType<TReturnType>()
=> new MockMethodImplementationGenerator<TArg1Input, TReturnType>();
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
using JetBrains.Annotations;

namespace MattSourceGenHelpers.Abstractions;

/// <summary>
/// Thrown when a partial method is called during source generation.
/// Partial methods cannot be invoked inside generator methods because they are the
/// methods being generated — they do not have an implementation yet at generation time.
/// </summary>
public class PartialMethodCalledDuringGenerationException : InvalidOperationException
{
public PartialMethodCalledDuringGenerationException(string methodName, string typeName)
: base(
$"Partial method '{typeName}.{methodName}' was called during source generation. " +
$"Partial methods cannot be invoked inside generator methods because their implementations " +
$"are what is being generated. Remove the call to '{methodName}' from your generator method.")
{
}
}
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)]
public class PartialMethodCalledDuringGenerationException(string methodName, string typeName) : InvalidOperationException(
$"Partial method '{typeName}.{methodName}' was called during source generation. " +
$"Partial methods cannot be invoked inside generator methods because their implementations " +
$"are what is being generated. Remove the call to '{methodName}' from your generator method.");
Loading