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
7 changes: 5 additions & 2 deletions ArchUnitNET/Loader/LoadTasks/AddMethodDependencies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,11 @@ private IEnumerable<MethodSignatureDependency> CreateMethodSignatureDependencies
MethodMember methodMember
)
{
return methodReference
.GetSignatureTypes(_typeFactory)
var returnType = methodReference.GetReturnType(_typeFactory);
return (returnType != null ? new[] { returnType } : Array.Empty<ITypeInstance<IType>>())
.Concat(methodReference.GetParameters(_typeFactory))
.Concat(methodReference.GetGenericParameters(_typeFactory))
.Distinct()
.Select(signatureType => new MethodSignatureDependency(
methodMember,
signatureType
Expand Down
66 changes: 12 additions & 54 deletions ArchUnitNET/Loader/MonoCecilMemberExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,75 +82,33 @@ this MethodDefinition methodDefinition
.Concat(methodDefinition.MethodReturnType.CustomAttributes);
}

[NotNull]
internal static IEnumerable<ITypeInstance<IType>> GetSignatureTypes(
this MethodReference methodReference,
TypeFactory typeFactory
)
{
var parameters = GetAllParameters(methodReference, typeFactory).ToList();
var returnType = GetReturnType(methodReference, typeFactory);
if (returnType != null)
{
parameters.Insert(0, returnType);
}

return parameters;
}

private static ITypeInstance<IType> GetReturnType(
internal static ITypeInstance<IType> GetReturnType(
this MethodReference methodReference,
TypeFactory typeFactory
)
{
return ReturnsVoid(methodReference)
) =>
ReturnsVoid(methodReference)
? null
: typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(
methodReference.MethodReturnType.ReturnType
);
}

[NotNull]
private static IEnumerable<ITypeInstance<IType>> GetAllParameters(
this MethodReference methodReference,
TypeFactory typeFactory
)
{
var parameters = methodReference.GetParameters(typeFactory).ToList();
var genericParameters = methodReference.GetGenericParameters(typeFactory).ToList();
parameters.AddRange(genericParameters);
return parameters;
}

[NotNull]
internal static IEnumerable<ITypeInstance<IType>> GetParameters(
this MethodReference method,
TypeFactory typeFactory
)
{
return method
.Parameters.Select(parameter =>
{
var typeReference = parameter.ParameterType;
return typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(typeReference);
})
.Distinct();
}
) =>
method.Parameters.Select(parameter =>
typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(parameter.ParameterType)
);

[NotNull]
private static IEnumerable<ITypeInstance<IType>> GetGenericParameters(
internal static IEnumerable<ITypeInstance<IType>> GetGenericParameters(
this MethodReference method,
TypeFactory typeFactory
)
{
return method
.GenericParameters.Select(parameter =>
{
var typeReference = parameter.GetElementType();
return typeFactory.GetOrCreateStubTypeInstanceFromTypeReference(typeReference);
})
.Distinct();
}
) =>
method.GenericParameters.Select(
typeFactory.GetOrCreateStubTypeInstanceFromTypeReference
);

[NotNull]
internal static IEnumerable<ITypeInstance<IType>> GetBodyTypes(
Expand Down
104 changes: 104 additions & 0 deletions ArchUnitNETTests/Loader/MonoCecilMemberExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System.Linq;
using ArchUnitNET.Domain;
using ArchUnitNET.Domain.Extensions;
using Xunit;
using static ArchUnitNETTests.StaticTestArchitectures;

namespace ArchUnitNETTests.Loader
{
public class MonoCecilMemberExtensionsTests
{
private static readonly Architecture LoaderTestArchitecture =
StaticTestArchitectures.LoaderTestArchitecture;

[Fact]
public void GetParameters_PreservesDuplicateParameterTypes()
{
var @class = LoaderTestArchitecture
.Types.OfType<Class>()
.FirstOrDefault(c => c.Name == "ClassWithDuplicateParameters");

Assert.NotNull(@class);

var method = @class
.GetMethodMembers()
.First(m => m.FullName.Contains("MethodWithSameParameterType"));

Assert.Equal(2, method.ParameterInstances.Count);
Assert.All(
method.ParameterInstances,
p => Assert.Equal("System.String", p.Type.FullName)
);
}

[Fact]
public void GetParameters_PreservesMultipleDuplicateParameterTypes()
{
var @class = LoaderTestArchitecture
.Types.OfType<Class>()
.FirstOrDefault(c => c.Name == "ClassWithDuplicateParameters");

Assert.NotNull(@class);

var method = @class
.GetMethodMembers()
.First(m => m.FullName.Contains("MethodWithTripleDuplicate"));

Assert.Equal(3, method.ParameterInstances.Count);
Assert.All(
method.ParameterInstances,
p => Assert.Equal("System.Int32", p.Type.FullName)
);
}

[Fact]
public void GetParameters_MixedTypeWithDuplicates()
{
var @class = LoaderTestArchitecture
.Types.OfType<Class>()
.FirstOrDefault(c => c.Name == "ClassWithDuplicateParameters");

Assert.NotNull(@class);

var method = @class
.GetMethodMembers()
.First(m => m.FullName.Contains("MethodWithMixedParamTypes"));

Assert.Equal(5, method.ParameterInstances.Count);

var stringParameters = method.ParameterInstances.Count(p =>
p.Type.FullName == "System.String"
);
var intParameters = method.ParameterInstances.Count(p =>
p.Type.FullName == "System.Int32"
);
var boolParameters = method.ParameterInstances.Count(p =>
p.Type.FullName == "System.Boolean"
);

Assert.Equal(3, stringParameters);
Assert.Equal(1, intParameters);
Assert.Equal(1, boolParameters);
}

[Fact]
public void GetParameters_CustomTypeDuplicates()
{
var @class = LoaderTestArchitecture
.Types.OfType<Class>()
.FirstOrDefault(c => c.Name == "ClassWithDuplicateParameters");

Assert.NotNull(@class);

var method = @class
.GetMethodMembers()
.First(m => m.FullName.Contains("MethodWithCustomTypeDuplicates"));

Assert.Equal(2, method.ParameterInstances.Count);
Assert.All(
method.ParameterInstances,
p => Assert.Contains("CustomType", p.Type.FullName)
);
}
}
}
13 changes: 13 additions & 0 deletions TestAssemblies/LoaderTestAssembly/LoaderTestAssembly.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
namespace LoaderTestAssembly;

public class LoaderTestAssembly { }

public class ClassWithDuplicateParameters
{
public void MethodWithSameParameterType(string param1, string param2) { }

public void MethodWithTripleDuplicate(int a, int b, int c) { }

public void MethodWithMixedParamTypes(string s1, int i, string s2, bool b, string s3) { }

public void MethodWithCustomTypeDuplicates(CustomType a, CustomType b) { }
}

public class CustomType { }
Loading