Skip to content

Commit

Permalink
Format method parameter type list more accurately
Browse files Browse the repository at this point in the history
This ensures that `in`, `ref`, `out`, and `params` modifiers are in-
cluded in the formatting of parameter type lists.
  • Loading branch information
stakx committed Aug 8, 2019
1 parent 76bc013 commit dfb2974
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
6 changes: 6 additions & 0 deletions src/Moq/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Text;

using Moq.Properties;

Expand Down Expand Up @@ -188,6 +189,11 @@ public static bool CompareTo<TTypes, TOtherTypes>(this TTypes types, TOtherTypes
return true;
}

public static string GetParameterTypeList(this MethodInfo method)
{
return new StringBuilder().AppendParameterTypeList(method.GetParameters()).ToString();
}

public static ParameterTypes GetParameterTypes(this MethodInfo method)
{
return new ParameterTypes(method.GetParameters());
Expand Down
6 changes: 2 additions & 4 deletions src/Moq/MethodCall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,12 @@ public void SetCallbackResponse(Delegate callback)
var expectedParamTypes = this.Method.GetParameterTypes();
if (!callback.CompareParameterTypesTo(expectedParamTypes))
{
// TODO: the following won't properly distinguish between `in`, `ref`, and `out` parameters!
var actualParams = callback.GetMethodInfo().GetParameters();
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.InvalidCallbackParameterMismatch,
string.Join(", ", expectedParamTypes.Select(p => p.GetFormattedName()).ToArray()),
string.Join(", ", actualParams.Select(p => p.ParameterType.GetFormattedName()).ToArray())));
this.Method.GetParameterTypeList(),
callback.GetMethodInfo().GetParameterTypeList()));
}

if (callback.GetMethodInfo().ReturnType != typeof(void))
Expand Down
48 changes: 48 additions & 0 deletions src/Moq/StringBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,54 @@ public static StringBuilder AppendNameOf(this StringBuilder stringBuilder, Type
return stringBuilder.AppendFormattedName(type);
}

public static StringBuilder AppendParameterType(this StringBuilder stringBuilder, ParameterInfo parameter)
{
var parameterType = parameter.ParameterType;

if (parameterType.IsByRef)
{
switch (parameter.Attributes & (ParameterAttributes.In | ParameterAttributes.Out))
{
case ParameterAttributes.In:
stringBuilder.Append("in ");
break;

case ParameterAttributes.Out:
stringBuilder.Append("out ");
break;

case ParameterAttributes.In | ParameterAttributes.Out:
default:
stringBuilder.Append("ref ");
break;
}

parameterType = parameterType.GetElementType();
}

if (parameterType.IsArray && parameter.IsDefined(typeof(ParamArrayAttribute), true))
{
stringBuilder.Append("params ");
}

return stringBuilder.AppendFormattedName(parameterType);
}

public static StringBuilder AppendParameterTypeList(this StringBuilder stringBuilder, ParameterInfo[] parameters)
{
for (int i = 0; i < parameters.Length; ++i)
{
if (i > 0)
{
stringBuilder.Append(", ");
}

stringBuilder.AppendParameterType(parameters[i]);
}

return stringBuilder;
}

public static StringBuilder AppendValueOf(this StringBuilder stringBuilder, object obj)
{
if (obj == null)
Expand Down
45 changes: 45 additions & 0 deletions tests/Moq.Tests/StringBuilderExtensionsFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD.
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.

using System.Text;

using Xunit;

namespace Moq.Tests
{
public class StringBuilderExtensionsFixture
{
[Theory]
[InlineData(nameof(IMethods.Empty), "")]
[InlineData(nameof(IMethods.Int), "int")]
[InlineData(nameof(IMethods.IntAndString), "int, string")]
[InlineData(nameof(IMethods.InInt), "in int")]
[InlineData(nameof(IMethods.RefInt), "ref int")]
[InlineData(nameof(IMethods.OutInt), "out int")]
[InlineData(nameof(IMethods.BoolAndParamsString), "bool, params string[]")]
public void AppendParameterList_formats_parameter_lists_correctly(string methodName, string expected)
{
var actual = GetFormattedParameterListOf(methodName);
Assert.Equal(expected, actual);
}

private string GetFormattedParameterListOf(string methodName)
{
var stringBuilder = new StringBuilder();
var method = typeof(IMethods).GetMethod(methodName);
stringBuilder.AppendParameterTypeList(method.GetParameters());
return stringBuilder.ToString();
}

public interface IMethods
{
void Empty();
void Int(int arg1);
void IntAndString(int arg1, string arg2);
void InInt(in int arg1);
void RefInt(ref int arg1);
void OutInt(out int arg1);
void BoolAndParamsString(bool arg1, params string[] arg2);
}
}
}

0 comments on commit dfb2974

Please sign in to comment.