diff --git a/Source/Mockolate.SourceGenerators/Sources/Sources.IndexerSetups.cs b/Source/Mockolate.SourceGenerators/Sources/Sources.IndexerSetups.cs index bec7ba19..dc37fee8 100644 --- a/Source/Mockolate.SourceGenerators/Sources/Sources.IndexerSetups.cs +++ b/Source/Mockolate.SourceGenerators/Sources/Sources.IndexerSetups.cs @@ -39,7 +39,7 @@ internal static class IndexerSetupExtensions """).AppendLine(); foreach (int item in indexerSetups) { - string types = string.Join(", ", Enumerable.Range(1, item).Select(i => $"T{i}")); + string types = GetGenericTypeParameters(item); sb.Append($$""" /// /// Extensions for indexer callback setups with {{item}} parameters. @@ -87,315 +87,162 @@ public void Forever() private static void AppendIndexerSetup(StringBuilder sb, int numberOfParameters) { - string typeParams = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(i => $"T{i}")); - string outTypeParams = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(i => $"out T{i}")); + string typeParams = GetGenericTypeParameters(numberOfParameters); + string outTypeParams = GetOutGenericTypeParameters(numberOfParameters); string parameters = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(i => $"p{i}")); string discards = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(_ => "_")); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Sets up a indexer getter for "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and .").AppendLine(); - sb.Append("\t/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a indexer getter for {GetTypeParametersDescription(numberOfParameters)}."); sb.Append("\tinternal interface IIndexerGetterSetup").AppendLine(); sb.Append("\t{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's getter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's getter is accessed.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action callback);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's getter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// The callback receives the parameters of the indexer.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's getter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action<") .Append(typeParams) .Append("> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's getter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives the parameters of the indexer and the value of the indexer as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's getter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer and the value of the indexer as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action<") .Append(typeParams) .Append(", TValue> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's getter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives an incrementing access counter as first parameter, the parameters of the indexer and the value of the indexer as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's getter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives an incrementing access counter as first parameter, the parameters of the indexer and the value of the indexer as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action callback);").AppendLine(); sb.Append("\t}").AppendLine(); sb.AppendLine(); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Sets up a indexer setter for "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and .").AppendLine(); - sb.Append("\t/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a indexer setter for {GetTypeParametersDescription(numberOfParameters)}."); sb.Append("\tinternal interface IIndexerSetterSetup").AppendLine(); sb.Append("\t{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's setter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's setter is accessed.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action callback);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's setter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// The callback receives the value the indexer is set to as single parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's setter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the value the indexer is set to as single parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's setter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives the parameters of the indexer and the value the indexer is set to as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's setter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer and the value the indexer is set to as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action<") .Append(typeParams).Append(", TValue> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a to be invoked whenever the indexer's setter is accessed.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives an incrementing access counter as first parameter, the parameters of the indexer and the value the indexer is set to as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to be invoked whenever the indexer's setter is accessed.", "\t\t"); + sb.AppendXmlRemarks("The callback receives an incrementing access counter as first parameter, the parameters of the indexer and the value the indexer is set to as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder Do(Action callback);").AppendLine(); sb.Append("\t}").AppendLine(); sb.AppendLine(); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Sets up a indexer for "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and .").AppendLine(); - sb.Append("\t/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a indexer for {GetTypeParametersDescription(numberOfParameters)}."); sb.Append("\tinternal interface IIndexerSetup").AppendLine(); sb.Append("\t{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Sets up callbacks on the getter.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Sets up callbacks on the getter.", "\t\t"); sb.Append("\t\tIIndexerGetterSetup OnGet { get; }").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Sets up callbacks on the setter.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Sets up callbacks on the setter.", "\t\t"); sb.Append("\t\tIIndexerSetterSetup OnSet { get; }").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Flag indicating if the base class implementation should be called, and its return values used as default values.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// If not specified, use .").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Flag indicating if the base class implementation should be called, and its return values used as default values.", "\t\t"); + sb.AppendXmlRemarks("If not specified, use .", "\t\t"); sb.Append("\t\tIIndexerSetup CallingBaseClass(bool callBaseClass = true);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Initializes the indexer with the given .").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Initializes the indexer with the given .", "\t\t"); sb.Append("\t\tIIndexerSetup InitializeWith(TValue value);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Initializes the according to the given .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Initializes the indexer according to the given .", "\t\t"); sb.Append("\t\tIIndexerSetup InitializeWith(Func<") .Append(typeParams).Append(", TValue> valueGenerator);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers the for this indexer.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers the for this indexer.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Returns(TValue returnValue);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to setup the return value for this indexer.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to setup the return value for this indexer.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Returns(Func callback);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to setup the return value for this indexer.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// The callback receives the parameters of the indexer.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to setup the return value for this indexer.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Returns(Func<") .Append(typeParams) .Append(", TValue> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to setup the return value for this indexer.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives the parameters of the indexer and the value of the indexer as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to setup the return value for this indexer.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer and the value of the indexer as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Returns(Func<") .Append(typeParams).Append(", TValue, TValue> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers an to throw when the indexer is read.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers an to throw when the indexer is read.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Throws()") .AppendLine(); sb.Append("\t\t\twhere TException : Exception, new();").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers an to throw when the indexer is read.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers an to throw when the indexer is read.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Throws(Exception exception);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a that will calculate the exception to throw when the indexer is read.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a that will calculate the exception to throw when the indexer is read.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Throws(Func callback);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a that will calculate the exception to throw when the indexer is read.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// The callback receives the parameters of the indexer.").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a that will calculate the exception to throw when the indexer is read.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Throws(Func<") .Append(typeParams) .Append(", Exception> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a that will calculate the exception to throw when the indexer is read.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// The callback receives the parameters of the indexer and the value of the indexer as last parameter.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a that will calculate the exception to throw when the indexer is read.", "\t\t"); + sb.AppendXmlRemarks("The callback receives the parameters of the indexer and the value of the indexer as last parameter.", "\t\t"); sb.Append("\t\tIIndexerSetupReturnBuilder Throws(Func<") .Append(typeParams).Append(", TValue, Exception> callback);").AppendLine(); sb.Append("\t}").AppendLine(); sb.AppendLine(); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Sets up a callback for a indexer for "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and .").AppendLine(); - sb.Append("\t/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a callback for a indexer for {GetTypeParametersDescription(numberOfParameters)}."); sb.Append("\tinternal interface IIndexerSetupCallbackBuilder : IIndexerSetupCallbackWhenBuilder").AppendLine(); sb.Append("\t{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Runs the callback in parallel to the other callbacks.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Runs the callback in parallel to the other callbacks.", "\t\t"); sb.Append("\t\tIIndexerSetupCallbackBuilder InParallel();") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Limits the callback to only execute for indexer accesses where the predicate returns true.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Limits the callback to only execute for indexer accesses where the predicate returns true.", "\t\t"); sb.Append("\t\t/// ").AppendLine(); sb.Append( "\t\t/// Provides a zero-based counter indicating how many times the indexer has been accessed so far.") diff --git a/Source/Mockolate.SourceGenerators/Sources/Sources.MethodSetups.cs b/Source/Mockolate.SourceGenerators/Sources/Sources.MethodSetups.cs index 41caef7f..a7316b52 100644 --- a/Source/Mockolate.SourceGenerators/Sources/Sources.MethodSetups.cs +++ b/Source/Mockolate.SourceGenerators/Sources/Sources.MethodSetups.cs @@ -44,7 +44,7 @@ internal static class MethodSetupExtensions """).AppendLine(); foreach ((int, bool) item in methodSetups) { - string genericParameters = string.Join(", ", Enumerable.Range(1, item.Item1).Select(i => $"T{i}")); + string genericParameters = GetGenericTypeParameters(item.Item1); if (!item.Item2) { genericParameters = "TReturn, " + genericParameters; @@ -106,161 +106,80 @@ public void Forever() private static void AppendVoidMethodSetup(StringBuilder sb, int numberOfParameters) { - string typeParams = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(i => $"T{i}")); + string typeParams = GetGenericTypeParameters(numberOfParameters); string parameters = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(i => $"p{i}")); string discards = string.Join(", ", Enumerable.Range(1, numberOfParameters).Select(_ => "_")); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Sets up a method with ").Append(numberOfParameters).Append(" parameters "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and returning .").AppendLine(); - sb.Append("\t/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a method with {numberOfParameters} parameters {GetTypeParametersDescription(numberOfParameters)} returning ."); sb.Append("\tinternal interface IVoidMethodSetup<").Append(typeParams).Append(">").AppendLine(); sb.Append("\t{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Flag indicating if the base class implementation should be called, and its return values used as default values.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// If not specified, use .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Flag indicating if the base class implementation should be called, and its return values used as default values.", "\t\t"); + sb.AppendXmlRemarks("If not specified, use .", "\t\t"); sb.Append("\t\tIVoidMethodSetup<").Append(typeParams).Append("> CallingBaseClass(bool callBaseClass = true);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to execute when the method is called.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to execute when the method is called.", "\t\t"); sb.Append("\t\tIVoidMethodSetupCallbackBuilder<").Append(typeParams).Append("> Do(Action callback);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to execute when the method is called.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to execute when the method is called.", "\t\t"); sb.Append("\t\tIVoidMethodSetupCallbackBuilder<").Append(typeParams).Append("> Do(Action<").Append(typeParams) .Append("> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers a to execute when the method is called.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a to execute when the method is called.", "\t\t"); sb.Append("\t\tIVoidMethodSetupCallbackBuilder<").Append(typeParams).Append("> Do(Action callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers an iteration in the sequence of method invocations, that does not throw.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers an iteration in the sequence of method invocations, that does not throw.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnBuilder<").Append(typeParams).Append("> DoesNotThrow();").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers an to throw when the method is invoked.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers an to throw when the method is invoked.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnBuilder<").Append(typeParams).Append("> Throws()") .AppendLine(); sb.Append("\t\t\twhere TException : Exception, new();").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// Registers an to throw when the method is invoked.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers an to throw when the method is invoked.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnBuilder<").Append(typeParams).Append("> Throws(Exception exception);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a that will calculate the exception to throw when the method is invoked.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a that will calculate the exception to throw when the method is invoked.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnBuilder<").Append(typeParams).Append("> Throws(Func<") .Append(typeParams).Append(", Exception> callback);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Registers a that will calculate the exception to throw when the method is invoked.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Registers a that will calculate the exception to throw when the method is invoked.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnBuilder<").Append(typeParams).Append("> Throws(Func callback);") .AppendLine(); sb.Append("}").AppendLine(); sb.AppendLine(); - sb.Append("/// ").AppendLine(); - sb.Append("/// Sets up a callback for a method with ").Append(numberOfParameters).Append(" parameters "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and returning .").AppendLine(); - sb.Append("/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a callback for a method with {numberOfParameters} parameters {GetTypeParametersDescription(numberOfParameters)} returning .", ""); sb.Append("internal interface IVoidMethodSetupCallbackBuilder<").Append(typeParams) .Append("> : IVoidMethodSetupCallbackWhenBuilder<").Append(typeParams).Append(">").AppendLine(); sb.Append("{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Runs the callback in parallel to the other callbacks.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Runs the callback in parallel to the other callbacks.", "\t\t"); sb.Append("\t\tIVoidMethodSetupCallbackBuilder<").Append(typeParams).Append("> InParallel();").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Limits the callback to only execute for indexer accesses where the predicate returns true.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Limits the callback to only execute for method invocations where the predicate returns true.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Provides a zero-based counter indicating how many times the method has been invoked so far.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Limits the callback to only execute for method invocations where the predicate returns true.", "\t\t"); + sb.AppendXmlRemarks("Provides a zero-based counter indicating how many times the method has been invoked so far.", "\t\t"); sb.Append("\t\tIVoidMethodSetupCallbackWhenBuilder<").Append(typeParams) .Append("> When(Func predicate);").AppendLine(); sb.Append("}").AppendLine(); sb.AppendLine(); - sb.Append("/// ").AppendLine(); - sb.Append("/// Sets up a when callback for a method with ").Append(numberOfParameters) - .Append(" parameters "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and returning .").AppendLine(); - sb.Append("/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a when callback for a method with {numberOfParameters} parameters {GetTypeParametersDescription(numberOfParameters)} returning .", ""); sb.Append("internal interface IVoidMethodSetupCallbackWhenBuilder<").Append(typeParams) .Append("> : IVoidMethodSetup<").Append(typeParams).Append(">").AppendLine(); sb.Append("{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Repeats the callback for the given number of .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Repeats the callback for the given number of .", "\t\t"); sb.Append("\t\t/// ").AppendLine(); sb.Append( "\t\t/// The number of times is only counted for actual executions ( For(int times);") .AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Deactivates the callback after the given number of .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Deactivates the callback after the given number of .", "\t\t"); sb.Append("\t\t/// ").AppendLine(); sb.Append( "\t\t/// The number of times is only counted for actual executions (").AppendLine(); - sb.Append("/// Sets up a return callback for a method with ").Append(numberOfParameters) - .Append(" parameters "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and returning .").AppendLine(); - sb.Append("/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a return callback for a method with {numberOfParameters} parameters {GetTypeParametersDescription(numberOfParameters)} returning .", ""); sb.Append("internal interface IVoidMethodSetupReturnBuilder<").Append(typeParams) .Append("> : IVoidMethodSetupReturnWhenBuilder<").Append(typeParams).Append(">").AppendLine(); sb.Append("{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Limits the throw to only execute for method invocations where the predicate returns true.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Provides a zero-based counter indicating how many times the method has been invoked so far.") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Limits the throw to only execute for method invocations where the predicate returns true.", "\t\t"); + sb.AppendXmlRemarks("Provides a zero-based counter indicating how many times the method has been invoked so far.", "\t\t"); sb.Append("\t\tIVoidMethodSetupReturnWhenBuilder<").Append(typeParams) .Append("> When(Func predicate);").AppendLine(); sb.Append("}").AppendLine(); sb.AppendLine(); - sb.Append("/// ").AppendLine(); - sb.Append("/// Sets up a when callback for a method with ").Append(numberOfParameters) - .Append(" parameters "); - for (int i = 1; i < numberOfParameters - 1; i++) - { - sb.Append(", "); - } - - sb.Append(" and returning .").AppendLine(); - sb.Append("/// ").AppendLine(); + sb.AppendXmlSummary($"Sets up a when callback for a method with {numberOfParameters} parameters {GetTypeParametersDescription(numberOfParameters)} returning .", ""); sb.Append("internal interface IVoidMethodSetupReturnWhenBuilder<").Append(typeParams) .Append("> : IVoidMethodSetup<").Append(typeParams).Append(">").AppendLine(); sb.Append("{").AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Repeats the throw for the given number of .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Repeats the throw for the given number of .", "\t\t"); sb.Append("\t\t/// ").AppendLine(); sb.Append( "\t\t/// The number of times is only counted for actual executions (").AppendLine(); sb.Append("\t\tIVoidMethodSetupReturnWhenBuilder<").Append(typeParams).Append("> For(int times);").AppendLine(); sb.AppendLine(); - sb.Append("\t\t/// ").AppendLine(); - sb.Append( - "\t\t/// Deactivates the throw after the given number of .") - .AppendLine(); - sb.Append("\t\t/// ").AppendLine(); + sb.AppendXmlSummary("Deactivates the throw after the given number of .", "\t\t"); sb.Append("\t\t/// ").AppendLine(); sb.Append( "\t\t/// The number of times is only counted for actual executions ((BaseClass.ConstructorParameters constructorParameters, sb.AppendLine(); for (int numberOfArguments = 1; numberOfArguments < maxNumberOfArguments; numberOfArguments++) { - string types = string.Join(", ", Enumerable.Range(2, numberOfArguments).Select(n => $"T{n}")); - sb.AppendLine("\t/// "); - sb.Append("\t/// Create a new mock for that also implements ") - .Append(numberOfArguments > 1 ? "interfaces " : "interface ") - .Append(string.Join(", ", - Enumerable.Range(2, numberOfArguments - 1).Select(n => $""))) - .Append(numberOfArguments > 1 ? " and " : "") - .Append("") - .Append(" with the default .").AppendLine(); - sb.AppendLine("\t/// "); + string types = GetGenericTypeParameters(numberOfArguments, 2); + sb.AppendXmlSummary($"Create a new mock for that also implements {GetAdditionalInterfacesDescription(numberOfArguments)} with the default ."); sb.AppendLine( "\t/// Type to mock, which can be an interface or a class."); - for (int i = 2; i <= numberOfArguments + 1; i++) - { - sb.Append("\t/// Additional interface that is implemented by the mock.").AppendLine(); - } + sb.AppendTypeParamDocs(numberOfArguments, "Additional interface that is implemented by the mock.", startIndex: 2); sb.AppendLine($$""" /// @@ -172,22 +160,10 @@ public static T Create(BaseClass.ConstructorParameters constructorParameters, """); sb.AppendLine(); - sb.AppendLine("\t/// "); - sb.Append("\t/// Create a new mock for that also implements ") - .Append(numberOfArguments > 1 ? "interfaces " : "interface ") - .Append(string.Join(", ", - Enumerable.Range(2, numberOfArguments - 1).Select(n => $""))) - .Append(numberOfArguments > 1 ? " and " : "") - .Append("") - .Append(" with the default .").AppendLine(); - sb.AppendLine("\t/// "); + sb.AppendXmlSummary($"Create a new mock for that also implements {GetAdditionalInterfacesDescription(numberOfArguments)} with the default ."); sb.AppendLine( "\t/// Type to mock, which can be an interface or a class."); - for (int i = 2; i <= numberOfArguments + 1; i++) - { - sb.Append("\t/// Additional interface that is implemented by the mock.").AppendLine(); - } + sb.AppendTypeParamDocs(numberOfArguments, "Additional interface that is implemented by the mock.", startIndex: 2); sb.AppendLine($$""" /// @@ -238,22 +214,10 @@ public static T Create(BaseClass.ConstructorParameters constructorParameters, """); sb.AppendLine(); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Create a new mock for that also implements ") - .Append(numberOfArguments > 1 ? "interfaces " : "interface ") - .Append(string.Join(", ", - Enumerable.Range(2, numberOfArguments - 1).Select(n => $""))) - .Append(numberOfArguments > 1 ? " and " : "") - .Append("") - .Append(" with the given .").AppendLine(); - sb.Append("\t/// ").AppendLine(); - sb.Append("\t/// Type to mock, which can be an interface or a class.") - .AppendLine(); - for (int i = 2; i <= numberOfArguments + 1; i++) - { - sb.Append("\t/// Additional interface that is implemented by the mock.").AppendLine(); - } + sb.AppendXmlSummary($"Create a new mock for that also implements {GetAdditionalInterfacesDescription(numberOfArguments)} with the given ."); + sb.AppendLine( + "\t/// Type to mock, which can be an interface or a class."); + sb.AppendTypeParamDocs(numberOfArguments, "Additional interface that is implemented by the mock.", startIndex: 2); sb.AppendLine($$""" /// @@ -326,23 +290,12 @@ public T Create(BaseClass.ConstructorParameters constructorParameters, params """); for (int numberOfArguments = 1; numberOfArguments < maxNumberOfArguments; numberOfArguments++) { - string types = string.Join(", ", Enumerable.Range(2, numberOfArguments).Select(n => $"T{n}")); + string types = GetGenericTypeParameters(numberOfArguments, 2); sb.AppendLine(); - sb.AppendLine("\t\t/// "); - sb.Append("\t\t/// Create a new mock for that also implements ") - .Append(numberOfArguments > 1 ? "interfaces " : "interface ") - .Append(string.Join(", ", - Enumerable.Range(2, numberOfArguments - 1).Select(n => $""))) - .Append(numberOfArguments > 1 ? " and " : "") - .Append(".").AppendLine(); - sb.AppendLine("\t\t/// "); + sb.AppendXmlSummary($"Create a new mock for that also implements {GetAdditionalInterfacesDescription(numberOfArguments)}.", "\t\t"); sb.AppendLine( "\t\t/// Type to mock, which can be an interface or a class."); - for (int i = 2; i <= numberOfArguments + 1; i++) - { - sb.Append("\t\t/// Additional interface that is implemented by the mock.").AppendLine(); - } + sb.AppendTypeParamDocs(numberOfArguments, "Additional interface that is implemented by the mock.", "\t\t", 2); sb.AppendLine($$""" /// @@ -360,21 +313,10 @@ public T Create(BaseClass.ConstructorParameters constructorParameters, params """); sb.AppendLine(); - sb.AppendLine("\t\t/// "); - sb.Append("\t\t/// Create a new mock for that also implements ") - .Append(numberOfArguments > 1 ? "interfaces " : "interface ") - .Append(string.Join(", ", - Enumerable.Range(2, numberOfArguments - 1).Select(n => $""))) - .Append(numberOfArguments > 1 ? " and " : "") - .Append(".").AppendLine(); - sb.AppendLine("\t\t/// "); + sb.AppendXmlSummary($"Create a new mock for that also implements {GetAdditionalInterfacesDescription(numberOfArguments)}.", "\t\t"); sb.AppendLine( "\t\t/// Type to mock, which can be an interface or a class."); - for (int i = 2; i <= numberOfArguments + 1; i++) - { - sb.Append("\t\t/// Additional interface that is implemented by the mock.").AppendLine(); - } + sb.AppendTypeParamDocs(numberOfArguments, "Additional interface that is implemented by the mock.", "\t\t", 2); sb.AppendLine($$""" /// @@ -576,5 +518,97 @@ internal static string GetString(this RefKind refKind) internal static string EscapeForXmlDoc(this string value) => value.Replace('<', '{').Replace('>', '}'); + + /// + /// Generates a comma-separated list of generic type parameters (e.g., "T1, T2, T3"). + /// + internal static string GetGenericTypeParameters(int count, int startIndex = 1) + => string.Join(", ", Enumerable.Range(startIndex, count).Select(i => $"T{i}")); + + /// + /// Generates a comma-separated list of generic type parameters with 'out' variance (e.g., "out T1, out T2"). + /// + internal static string GetOutGenericTypeParameters(int count, int startIndex = 1) + => string.Join(", ", Enumerable.Range(startIndex, count).Select(i => $"out T{i}")); + + /// + /// Appends XML documentation summary tags with the given text. + /// + internal static StringBuilder AppendXmlSummary(this StringBuilder sb, string summaryText, string indent = "\t") + { + sb.Append(indent).Append("/// ").AppendLine(); + sb.Append(indent).Append("/// ").Append(summaryText).AppendLine(); + sb.Append(indent).Append("/// ").AppendLine(); + return sb; + } + + /// + /// Appends XML documentation remarks tags with the given text. + /// + internal static StringBuilder AppendXmlRemarks(this StringBuilder sb, string remarksText, string indent = "\t\t") + { + sb.Append(indent).Append("/// ").AppendLine(); + sb.Append(indent).Append("/// ").Append(remarksText).AppendLine(); + sb.Append(indent).Append("/// ").AppendLine(); + return sb; + } + + /// + /// Generates a descriptive text listing type parameters (e.g., "T1, T2 and T3" or just "T1"). + /// + internal static string GetTypeParametersDescription(int numberOfParameters, int startIndex = 1) + { + if (numberOfParameters == 1) + { + return $""; + } + + StringBuilder sb = new(); + for (int i = startIndex; i < startIndex + numberOfParameters - 1; i++) + { + if (i > startIndex) + { + sb.Append(", "); + } + sb.Append(""); + } + sb.Append(" and "); + return sb.ToString(); + } + + /// + /// Appends type parameter XML documentation for generic parameters. + /// + internal static StringBuilder AppendTypeParamDocs(this StringBuilder sb, int count, string description, string indent = "\t", int startIndex = 1) + { + for (int i = startIndex; i < startIndex + count; i++) + { + sb.Append(indent).Append("/// ").Append(description).AppendLine(""); + } + return sb; + } + + /// + /// Generates description text for additional interfaces (e.g., "interface T2" or "interfaces T2, T3 and T4"). + /// + internal static string GetAdditionalInterfacesDescription(int numberOfArguments, int startIndex = 2) + { + if (numberOfArguments == 1) + { + return $"interface "; + } + + StringBuilder sb = new("interfaces "); + for (int i = startIndex; i < startIndex + numberOfArguments - 1; i++) + { + if (i > startIndex) + { + sb.Append(", "); + } + sb.Append(""); + } + sb.Append(" and "); + return sb.ToString(); + } } #pragma warning restore S3776 // Cognitive Complexity of methods should not be too high