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
24 changes: 24 additions & 0 deletions TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,28 @@ void M()

return VerifyGeneratorOutput(source);
}

[Test]
public Task Interface_With_Keyword_Parameter_Names()
{
var source = """
using TUnit.Mocks;

public interface ITest
{
void Test(string @event);
string Get(int @class, string @return);
}

public class TestUsage
{
void M()
{
var mock = Mock.Of<ITest>();
}
}
""";

return VerifyGeneratorOutput(source);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
{
internal static class ITest_MockFactory
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void Register()
{
global::TUnit.Mocks.Mock.RegisterFactory<global::ITest>(Create);
}

private static global::TUnit.Mocks.Mock<global::ITest> Create(global::TUnit.Mocks.MockBehavior behavior)
{
var engine = new global::TUnit.Mocks.MockEngine<global::ITest>(behavior);
var impl = new ITest_MockImpl(engine);
engine.Raisable = impl;
var mock = new global::TUnit.Mocks.Mock<global::ITest>(impl, engine);
return mock;
}
}
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
{
internal sealed class ITest_MockImpl : global::ITest, global::TUnit.Mocks.IRaisable
{
private readonly global::TUnit.Mocks.MockEngine<global::ITest> _engine;

internal ITest_MockImpl(global::TUnit.Mocks.MockEngine<global::ITest> engine)
{
_engine = engine;
}

public void Test(string @event)
{
_engine.HandleCall(0, "Test", new object?[] { @event });
}

public string Get(int @class, string @return)
{
return _engine.HandleCallWithReturn<string>(1, "Get", new object?[] { @class, @return }, "");
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public void RaiseEvent(string eventName, object? args)
{
throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock.");
}
}
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
{
public static class ITest_MockMemberExtensions
{
public static ITest_Test_M0_MockCall Test(this global::TUnit.Mocks.Mock<global::ITest> mock, global::TUnit.Mocks.Arguments.Arg<string> @event)
{
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { @event.Matcher };
return new ITest_Test_M0_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 0, "Test", matchers);
}

public static ITest_Test_M0_MockCall Test(this global::TUnit.Mocks.Mock<global::ITest> mock, global::System.Func<string, bool> @event)
{
global::TUnit.Mocks.Arguments.Arg<string> __fa_event = @event;
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { __fa_event.Matcher };
return new ITest_Test_M0_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 0, "Test", matchers);
}

public static ITest_Get_M1_MockCall Get(this global::TUnit.Mocks.Mock<global::ITest> mock, global::TUnit.Mocks.Arguments.Arg<int> @class, global::TUnit.Mocks.Arguments.Arg<string> @return)
{
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { @class.Matcher, @return.Matcher };
return new ITest_Get_M1_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 1, "Get", matchers);
}

public static ITest_Get_M1_MockCall Get(this global::TUnit.Mocks.Mock<global::ITest> mock, global::System.Func<int, bool> @class, global::TUnit.Mocks.Arguments.Arg<string> @return)
{
global::TUnit.Mocks.Arguments.Arg<int> __fa_class = @class;
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { __fa_class.Matcher, @return.Matcher };
return new ITest_Get_M1_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 1, "Get", matchers);
}

public static ITest_Get_M1_MockCall Get(this global::TUnit.Mocks.Mock<global::ITest> mock, global::TUnit.Mocks.Arguments.Arg<int> @class, global::System.Func<string, bool> @return)
{
global::TUnit.Mocks.Arguments.Arg<string> __fa_return = @return;
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { @class.Matcher, __fa_return.Matcher };
return new ITest_Get_M1_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 1, "Get", matchers);
}

public static ITest_Get_M1_MockCall Get(this global::TUnit.Mocks.Mock<global::ITest> mock, global::System.Func<int, bool> @class, global::System.Func<string, bool> @return)
{
global::TUnit.Mocks.Arguments.Arg<int> __fa_class = @class;
global::TUnit.Mocks.Arguments.Arg<string> __fa_return = @return;
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { __fa_class.Matcher, __fa_return.Matcher };
return new ITest_Get_M1_MockCall(global::TUnit.Mocks.Mock.GetEngine(mock), 1, "Get", matchers);
}
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class ITest_Test_M0_MockCall : global::TUnit.Mocks.Verification.ICallVerification
{
private readonly global::TUnit.Mocks.IMockEngineAccess _engine;
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder> _lazyBuilder;

internal ITest_Test_M0_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder>(() =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
}
);
_ = _lazyBuilder.Value;
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() => _lazyBuilder.Value;

/// <inheritdoc />
public ITest_Test_M0_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Throws(global::System.Exception exception) { EnsureSetup().Throws(exception); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Callback(global::System.Action callback) { EnsureSetup().Callback(callback); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Callback(global::System.Action<object?[]> callback) { EnsureSetup().Callback(callback); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Throws(global::System.Func<object?[], global::System.Exception> exceptionFactory) { EnsureSetup().Throws(exceptionFactory); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Raises(string eventName, object? args = null) { EnsureSetup().Raises(eventName, args); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall SetsOutParameter(int paramIndex, object? value) { EnsureSetup().SetsOutParameter(paramIndex, value); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall TransitionsTo(string stateName) { EnsureSetup().TransitionsTo(stateName); return this; }
/// <inheritdoc />
public ITest_Test_M0_MockCall Then() { EnsureSetup().Then(); return this; }

/// <summary>Execute a typed callback using the actual method parameters.</summary>
public ITest_Test_M0_MockCall Callback(global::System.Action<string> callback)
{
EnsureSetup().Callback(args => callback((string)args[0]!));
return this;
}

/// <summary>Configure a typed computed exception using the actual method parameters.</summary>
public ITest_Test_M0_MockCall Throws(global::System.Func<string, global::System.Exception> exceptionFactory)
{
EnsureSetup().Throws(args => exceptionFactory((string)args[0]!));
return this;
}

// ICallVerification
/// <inheritdoc />
public void WasCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled();
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times);
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times, string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times, message);
/// <inheritdoc />
public void WasCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(message);
/// <inheritdoc />
public void WasNeverCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled();
/// <inheritdoc />
public void WasNeverCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled(message);
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class ITest_Get_M1_MockCall : global::TUnit.Mocks.Verification.ICallVerification
{
private readonly global::TUnit.Mocks.IMockEngineAccess _engine;
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>> _lazyBuilder;

internal ITest_Get_M1_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>>(() =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.MethodSetupBuilder<string>(setup);
}
);
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<string> EnsureSetup() => _lazyBuilder.Value;

/// <inheritdoc />
public ITest_Get_M1_MockCall Returns(string value) { EnsureSetup().Returns(value); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Returns(global::System.Func<string> factory) { EnsureSetup().Returns(factory); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall ReturnsSequentially(params string[] values) { EnsureSetup().ReturnsSequentially(values); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Throws(global::System.Exception exception) { EnsureSetup().Throws(exception); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Callback(global::System.Action callback) { EnsureSetup().Callback(callback); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Callback(global::System.Action<object?[]> callback) { EnsureSetup().Callback(callback); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Returns(global::System.Func<object?[], string> factory) { EnsureSetup().Returns(factory); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Throws(global::System.Func<object?[], global::System.Exception> exceptionFactory) { EnsureSetup().Throws(exceptionFactory); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Raises(string eventName, object? args = null) { EnsureSetup().Raises(eventName, args); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall SetsOutParameter(int paramIndex, object? value) { EnsureSetup().SetsOutParameter(paramIndex, value); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall TransitionsTo(string stateName) { EnsureSetup().TransitionsTo(stateName); return this; }
/// <inheritdoc />
public ITest_Get_M1_MockCall Then() { EnsureSetup().Then(); return this; }

/// <summary>Configure a typed computed return value using the actual method parameters.</summary>
public ITest_Get_M1_MockCall Returns(global::System.Func<int, string, string> factory)
{
EnsureSetup().Returns(args => factory((int)args[0]!, (string)args[1]!));
return this;
}

/// <summary>Execute a typed callback using the actual method parameters.</summary>
public ITest_Get_M1_MockCall Callback(global::System.Action<int, string> callback)
{
EnsureSetup().Callback(args => callback((int)args[0]!, (string)args[1]!));
return this;
}

/// <summary>Configure a typed computed exception using the actual method parameters.</summary>
public ITest_Get_M1_MockCall Throws(global::System.Func<int, string, global::System.Exception> exceptionFactory)
{
EnsureSetup().Throws(args => exceptionFactory((int)args[0]!, (string)args[1]!));
return this;
}

// ICallVerification
/// <inheritdoc />
public void WasCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled();
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times);
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times, string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times, message);
/// <inheritdoc />
public void WasCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(message);
/// <inheritdoc />
public void WasNeverCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled();
/// <inheritdoc />
public void WasNeverCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled(message);
}
}
11 changes: 8 additions & 3 deletions TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,10 @@ private static void GenerateTypedOutRefMethods(CodeWriter writer, EquatableArray
}

private static string ToPascalCase(string name)
=> string.IsNullOrEmpty(name) ? name : char.ToUpperInvariant(name[0]) + name[1..];
{
if (name.StartsWith("@")) name = name[1..];
return string.IsNullOrEmpty(name) ? name : char.ToUpperInvariant(name[0]) + name[1..];
}

private static string BuildCastArgs(List<MockParameterModel> nonOutParams, List<MockParameterModel>? allNonOutParams = null)
{
Expand Down Expand Up @@ -674,7 +677,8 @@ private static void EmitSingleFuncOverload(CodeWriter writer, MockMemberModel me
foreach (var idx in funcIndices.OrderBy(i => i))
{
var p = method.Parameters[idx];
writer.AppendLine($"global::TUnit.Mocks.Arguments.Arg<{p.FullyQualifiedType}> __fa_{p.Name} = {p.Name};");
var rawName = p.Name.StartsWith("@") ? p.Name[1..] : p.Name;
writer.AppendLine($"global::TUnit.Mocks.Arguments.Arg<{p.FullyQualifiedType}> __fa_{rawName} = {p.Name};");
}

// Build matchers array
Expand All @@ -685,7 +689,8 @@ private static void EmitSingleFuncOverload(CodeWriter writer, MockMemberModel me
if (p.Direction == ParameterDirection.Out) continue;
if (!includeRefStructArgs && p.IsRefStruct) continue;

matcherExprs.Add(funcIndices.Contains(i) ? $"__fa_{p.Name}.Matcher" : $"{p.Name}.Matcher");
var rawName = p.Name.StartsWith("@") ? p.Name[1..] : p.Name;
matcherExprs.Add(funcIndices.Contains(i) ? $"__fa_{rawName}.Matcher" : $"{p.Name}.Matcher");
}

if (matcherExprs.Count == 0)
Expand Down
Loading
Loading