diff --git a/Source/Mockolate.SourceGenerators/Sources/Sources.MockClass.cs b/Source/Mockolate.SourceGenerators/Sources/Sources.MockClass.cs index 57f66c0a..8298a488 100644 --- a/Source/Mockolate.SourceGenerators/Sources/Sources.MockClass.cs +++ b/Source/Mockolate.SourceGenerators/Sources/Sources.MockClass.cs @@ -11,7 +11,7 @@ namespace Mockolate.SourceGenerators.Sources; internal static partial class Sources { private const int MaxExplicitParameters = 4; - + public static string MockClass(string name, Class @class) { EquatableArray? constructors = (@class as MockClass)?.Constructors; @@ -1740,7 +1740,7 @@ private static void DefineSetupInterface(StringBuilder sb, Class @class, MemberT property.MemberType == memberType; foreach (Property property in @class.AllProperties().Where(propertyPredicate)) { - sb.AppendXmlSummary($"Setup for the {property.Type.Fullname.EscapeForXmlDoc()} property ."); + sb.AppendXmlSummary($"Setup for the {property.Type.Fullname.EscapeForXmlDoc()} property ."); sb.Append("\t\tglobal::Mockolate.Setup.PropertySetup<").Append(property.Type.Fullname).Append("> ").Append(property.Name).Append(" { get; }").AppendLine(); sb.AppendLine(); } @@ -1754,12 +1754,12 @@ private static void DefineSetupInterface(StringBuilder sb, Class @class, MemberT indexer.MemberType == memberType; foreach (Property indexer in @class.AllProperties().Where(indexerPredicate)) { - AppendIndexerSetupDefinition(sb, @class, indexer); + AppendIndexerSetupDefinition(sb, indexer); if (indexer.IndexerParameters!.Value.Count <= MaxExplicitParameters) { foreach (bool[] valueFlags in GenerateValueFlagCombinations(indexer.IndexerParameters.Value)) { - AppendIndexerSetupDefinition(sb, @class, indexer, valueFlags); + AppendIndexerSetupDefinition(sb, indexer, valueFlags); } } else @@ -1767,7 +1767,7 @@ private static void DefineSetupInterface(StringBuilder sb, Class @class, MemberT bool[] allValueFlags = indexer.IndexerParameters.Value.Select(p => p.CanBeExplicitValue()).ToArray(); if (allValueFlags.Any(f => f)) { - AppendIndexerSetupDefinition(sb, @class, indexer, allValueFlags); + AppendIndexerSetupDefinition(sb, indexer, allValueFlags); } } } @@ -1830,7 +1830,7 @@ private static void AppendMethodSetupDefinition(StringBuilder sb, Class @class, if (methodNameOverride is null) { sb.Append("\t\t/// Setup for the method p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))) @@ -2004,7 +2004,7 @@ private static void ImplementSetupInterface(StringBuilder sb, Class @class, stri Func methodPredicate = method => method.ExplicitImplementation is null && method.MemberType == memberType; - + List> methodGroups = @class.AllMethods().Where(methodPredicate).GroupBy(m => m.Name).ToList(); foreach (IGrouping? methodGroup in methodGroups) { @@ -2016,6 +2016,7 @@ private static void ImplementSetupInterface(StringBuilder sb, Class @class, stri AppendMethodSetupImplementation(sb, method, mockRegistryName, setupName, true); } } + foreach (Method? method in methodGroup) { if (method.Parameters.Count == 0) @@ -2193,10 +2194,10 @@ private static void AppendMethodSetupImplementation(StringBuilder sb, Method met sb.AppendLine(); } - private static void AppendIndexerSetupDefinition(StringBuilder sb, Class @class, Property indexer, bool[]? valueFlags = null) + private static void AppendIndexerSetupDefinition(StringBuilder sb, Property indexer, bool[]? valueFlags = null) { sb.AppendXmlSummary( - $"Setup for the {indexer.Type.Fullname.EscapeForXmlDoc()} indexer p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))}]\" />"); + $"Setup for the {indexer.Type.Fullname.EscapeForXmlDoc()} indexer p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))}]\" />"); sb.Append("\t\tglobal::Mockolate.Setup.IndexerSetup<").AppendTypeOrWrapper(indexer.Type); foreach (MethodParameter parameter in indexer.IndexerParameters!) { @@ -2320,10 +2321,10 @@ private static void AppendIndexerSetupImplementation(StringBuilder sb, Property sb.AppendLine(); } - private static void AppendIndexerVerifyDefinition(StringBuilder sb, Class @class, Property indexer, string verifyName, bool[]? valueFlags = null) + private static void AppendIndexerVerifyDefinition(StringBuilder sb, Property indexer, string verifyName, bool[]? valueFlags = null) { sb.AppendXmlSummary( - $"Verify interactions with the {indexer.Type.Fullname.EscapeForXmlDoc()} indexer p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))}]\" />"); + $"Verify interactions with the {indexer.Type.Fullname.EscapeForXmlDoc()} indexer p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))}]\" />."); sb.Append("\t\tglobal::Mockolate.Verify.VerificationIndexerResult<").Append(verifyName).Append(", ").AppendTypeOrWrapper(indexer.Type).Append("> this["); int i = 0; foreach (MethodParameter parameter in indexer.IndexerParameters!.Value) @@ -2426,21 +2427,20 @@ private static void DefineRaiseInterface(StringBuilder sb, Class @class, MemberT @event.MemberType == memberType; foreach (Event @event in @class.AllEvents().Where(predicate)) { - sb.AppendXmlSummary($"Raise the event."); + sb.AppendXmlSummary($"Raise the event."); sb.Append("\t\tvoid ").Append(@event.Name).Append("(").Append(FormatParametersWithTypeAndName(@event.Delegate.Parameters)).Append(");").AppendLine(); sb.AppendLine(); } - foreach (string? eventName in @class.AllEvents() + foreach (Event @event in @class.AllEvents() .Where(predicate) .GroupBy(m => m.Name) .Where(g => g.Count() == 1) .Select(g => g.Single()) - .Where(m => m.Delegate.Parameters.Count > 0) - .Select(x => x.Name)) + .Where(m => m.Delegate.Parameters.Count > 0)) { - sb.AppendXmlSummary($"Raise the event."); - sb.Append("\t\tvoid ").Append(eventName).Append("(global::Mockolate.Parameters.IDefaultEventParameters parameters);").AppendLine(); + sb.AppendXmlSummary($"Raise the event."); + sb.Append("\t\tvoid ").Append(@event.Name).Append("(global::Mockolate.Parameters.IDefaultEventParameters parameters);").AppendLine(); sb.AppendLine(); } } @@ -2506,7 +2506,7 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string property.MemberType == memberType; foreach (Property property in @class.AllProperties().Where(propertyPredicate)) { - sb.AppendXmlSummary($"Verify interactions with the {property.Type.Fullname.EscapeForXmlDoc()} property ."); + sb.AppendXmlSummary($"Verify interactions with the {property.Type.Fullname.EscapeForXmlDoc()} property ."); sb.Append("\t\tglobal::Mockolate.Verify.VerificationPropertyResult<").Append(verifyName).Append(", ").Append(property.Type.Fullname).Append("> ").Append(property.Name).Append(" { get; }").AppendLine(); sb.AppendLine(); } @@ -2520,12 +2520,12 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string indexer.MemberType == memberType; foreach (Property indexer in @class.AllProperties().Where(indexerPredicate)) { - AppendIndexerVerifyDefinition(sb, @class, indexer, verifyName); + AppendIndexerVerifyDefinition(sb, indexer, verifyName); if (indexer.IndexerParameters!.Value.Count <= MaxExplicitParameters) { foreach (bool[] valueFlags in GenerateValueFlagCombinations(indexer.IndexerParameters.Value)) { - AppendIndexerVerifyDefinition(sb, @class, indexer, verifyName, valueFlags); + AppendIndexerVerifyDefinition(sb, indexer, verifyName, valueFlags); } } else @@ -2533,7 +2533,7 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string bool[] allValueFlags = indexer.IndexerParameters.Value.Select(p => p.CanBeExplicitValue()).ToArray(); if (allValueFlags.Any(f => f)) { - AppendIndexerVerifyDefinition(sb, @class, indexer, verifyName, allValueFlags); + AppendIndexerVerifyDefinition(sb, indexer, verifyName, allValueFlags); } } } @@ -2553,7 +2553,7 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string Method? method = methodGroup.Single(); if (method.Parameters.Count > 0) { - AppendMethodVerifyDefinition(sb, @class, method, verifyName, true); + AppendMethodVerifyDefinition(sb, method, verifyName, true); } } @@ -2561,16 +2561,16 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string { if (method.Parameters.Count == 0) { - AppendMethodVerifyDefinition(sb, @class, method, verifyName, false); + AppendMethodVerifyDefinition(sb, method, verifyName, false); } else { - AppendMethodVerifyDefinition(sb, @class, method, verifyName, false); + AppendMethodVerifyDefinition(sb, method, verifyName, false); if (method.Parameters.Count <= MaxExplicitParameters) { foreach (bool[] valueFlags in GenerateValueFlagCombinations(method.Parameters)) { - AppendMethodVerifyDefinition(sb, @class, method, verifyName, false, valueFlags: valueFlags); + AppendMethodVerifyDefinition(sb, method, verifyName, false, valueFlags: valueFlags); } } else @@ -2578,7 +2578,7 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string bool[] allValueFlags = method.Parameters.Select(p => p.CanBeExplicitValue()).ToArray(); if (allValueFlags.Any(f => f)) { - AppendMethodVerifyDefinition(sb, @class, method, verifyName, false, valueFlags: allValueFlags); + AppendMethodVerifyDefinition(sb, method, verifyName, false, valueFlags: allValueFlags); } } } @@ -2591,23 +2591,23 @@ private static void DefineVerifyInterface(StringBuilder sb, Class @class, string Func eventPredicate = @event => @event.ExplicitImplementation is null && @event.MemberType == memberType; - foreach (string eventName in @class.AllEvents().Where(eventPredicate).Select(e => e.Name)) + foreach (Event @event in @class.AllEvents().Where(eventPredicate)) { - sb.AppendXmlSummary($"Verify subscription on the {eventName} event ."); - sb.Append("\t\tglobal::Mockolate.Verify.VerificationEventResult<").Append(verifyName).Append("> ").Append(eventName).Append(" { get; }").AppendLine(); + sb.AppendXmlSummary($"Verify subscriptions on the {@event.Name} event of ."); + sb.Append("\t\tglobal::Mockolate.Verify.VerificationEventResult<").Append(verifyName).Append("> ").Append(@event.Name).Append(" { get; }").AppendLine(); sb.AppendLine(); } #endregion } - private static void AppendMethodVerifyDefinition(StringBuilder sb, Class @class, Method method, string verifyName, + private static void AppendMethodVerifyDefinition(StringBuilder sb, Method method, string verifyName, bool useParameters, string? methodNameOverride = null, bool[]? valueFlags = null) { string methodName = methodNameOverride ?? method.Name; sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Validates the invocations for the method p.RefKind.GetString() + p.Type.Fullname.EscapeForXmlDoc()))); @@ -2779,7 +2779,7 @@ private static void ImplementVerifyInterface(StringBuilder sb, Class @class, str @event.MemberType == memberType; foreach (Event @event in @class.AllEvents().Where(eventPredicate)) { - sb.AppendXmlSummary($"Verify subscription on the {@event.Name} event ."); + sb.AppendXmlSummary($"Verify subscriptions on the {@event.Name} event ."); sb.Append("\t\t[global::System.Diagnostics.DebuggerBrowsable(global::System.Diagnostics.DebuggerBrowsableState.Never)]").AppendLine(); sb.Append("\t\tglobal::Mockolate.Verify.VerificationEventResult<").Append(verifyName).Append("> ").Append(verifyName).Append('.').Append(@event.Name).AppendLine(); sb.Append("\t\t{").AppendLine(); diff --git a/Source/Mockolate.SourceGenerators/Sources/Sources.MockDelegate.cs b/Source/Mockolate.SourceGenerators/Sources/Sources.MockDelegate.cs index 3a95e9fd..d767d12f 100644 --- a/Source/Mockolate.SourceGenerators/Sources/Sources.MockDelegate.cs +++ b/Source/Mockolate.SourceGenerators/Sources/Sources.MockDelegate.cs @@ -167,12 +167,12 @@ public static string MockDelegate(string name, MockClass @class, Method delegate sb.Append("\t\t}").AppendLine(); sb.AppendLine(); - + sb.Append("\t\t/// ").AppendLine(); sb.Append("\t\tstring global::Mockolate.IMock.ToString()").AppendLine(); sb.Append("\t\t\t=> \"").Append(@class.DisplayString).Append(" mock\";").AppendLine(); sb.AppendLine(); - + AppendMethodSetupImplementation(sb, delegateMethod, mockRegistryName, $"IMockSetupFor{name}", false, "Setup"); if (delegateMethod.Parameters.Count > 0) { @@ -343,17 +343,17 @@ public static string MockDelegate(string name, MockClass @class, Method delegate sb.AppendXmlSummary($"Verify interactions with the mock of .", "\t"); sb.Append("\tinternal interface IMockVerifyFor").Append(name).Append(" : global::Mockolate.Verify.IMockVerify<").Append(@class.ClassFullName).Append(">").AppendLine(); sb.Append("\t{").AppendLine(); - AppendMethodVerifyDefinition(sb, @class, delegateMethod, $"IMockVerifyFor{name}", false, "Verify"); + AppendMethodVerifyDefinition(sb, delegateMethod, $"IMockVerifyFor{name}", false, "Verify"); if (delegateMethod.Parameters.Count > 0) { - AppendMethodVerifyDefinition(sb, @class, delegateMethod, $"IMockVerifyFor{name}", true, "Verify"); + AppendMethodVerifyDefinition(sb, delegateMethod, $"IMockVerifyFor{name}", true, "Verify"); } if (delegateMethod.Parameters.Count is > 0 and <= MaxExplicitParameters) { foreach (bool[] valueFlags in GenerateValueFlagCombinations(delegateMethod.Parameters)) { - AppendMethodVerifyDefinition(sb, @class, delegateMethod, $"IMockVerifyFor{name}", false, "Verify", valueFlags); + AppendMethodVerifyDefinition(sb, delegateMethod, $"IMockVerifyFor{name}", false, "Verify", valueFlags); } } else if (delegateMethod.Parameters.Count > MaxExplicitParameters) @@ -361,7 +361,7 @@ public static string MockDelegate(string name, MockClass @class, Method delegate bool[] allValueFlags = delegateMethod.Parameters.Select(p => p.CanBeExplicitValue()).ToArray(); if (allValueFlags.Any(f => f)) { - AppendMethodVerifyDefinition(sb, @class, delegateMethod, $"IMockVerifyFor{name}", false, "Verify", allValueFlags); + AppendMethodVerifyDefinition(sb, delegateMethod, $"IMockVerifyFor{name}", false, "Verify", allValueFlags); } } diff --git a/Tests/Mockolate.SourceGenerators.Tests/MockTests.ClassTests.cs b/Tests/Mockolate.SourceGenerators.Tests/MockTests.ClassTests.cs index b0ce96ec..dd168326 100644 --- a/Tests/Mockolate.SourceGenerators.Tests/MockTests.ClassTests.cs +++ b/Tests/Mockolate.SourceGenerators.Tests/MockTests.ClassTests.cs @@ -41,5 +41,46 @@ await That(result.Sources).ContainsKey("Mock.MyService.g.cs").WhoseValue .Contains("return baseResult1;") .IgnoringNewlineStyle(); } + + [Fact] + public async Task InheritedInterface_ShouldHaveCorrectReferenceInXMLDocumentation() + { + GeneratorResult result = Generator + .Run(""" + using System; + using Mockolate; + + namespace MyCode; + + public class Program + { + public static void Main(string[] args) + { + _ = IMyService.CreateMock(); + } + } + + public interface IMyService : IMyBaseService + { + } + public interface IMyBaseService + { + int BaseProperty { get; } + event EventHandler BaseEvent; + int BaseMethod(); + int this[string baseIndexer] { get; } + } + """); + + await That(result.Sources).ContainsKey("Mock.IMyService.g.cs").WhoseValue + .Contains("Setup for the int property .").And + .Contains("Verify interactions with the int property .").And + .Contains("Setup for the int indexer ").And + .Contains("Verify interactions with the int indexer .").And + .Contains("Setup for the method .").And + .Contains("Verify invocations for the method .").And + .Contains("Raise the event.").And + .Contains("Verify subscriptions on the BaseEvent event of ."); + } } }