Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/cecil.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mono.Cecil/AssemblyReader.cs4
-rw-r--r--Mono.Cecil/AssemblyWriter.cs8
-rw-r--r--Mono.Cecil/FieldDefinition.cs2
-rw-r--r--Mono.Cecil/GenericParameterResolver.cs175
-rw-r--r--Mono.Cecil/MemberReference.cs5
-rw-r--r--Mono.Cecil/MethodDefinition.cs2
-rw-r--r--Mono.Cecil/MethodReferenceComparer.cs143
-rw-r--r--Mono.Cecil/Treatments.cs7
-rw-r--r--Mono.Cecil/TypeComparisonMode.cs12
-rw-r--r--Mono.Cecil/TypeReference.cs2
-rw-r--r--Mono.Cecil/TypeReferenceEqualityComparer.cs253
-rw-r--r--Mono.Cecil/TypeResolver.cs220
-rw-r--r--Mono.Cecil/WindowsRuntimeProjections.cs248
-rw-r--r--Test/Mono.Cecil.Tests/LoadAssemblyDefinitionForTestsBaseSimple.cs16
-rw-r--r--Test/Mono.Cecil.Tests/MethodReferenceComparerTests.cs135
-rw-r--r--Test/Mono.Cecil.Tests/TypeDefinitionUtils.cs41
-rw-r--r--Test/Mono.Cecil.Tests/TypeReferenceComparisonTests.cs84
-rw-r--r--Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs144
-rw-r--r--Test/Resources/assemblies/NativeWinmd.winmdbin3584 -> 4608 bytes
19 files changed, 1401 insertions, 100 deletions
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index 3dae1e4..d18a51e 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -2326,10 +2326,6 @@ namespace Mono.Cecil {
}
member.token = new MetadataToken (TokenType.MemberRef, rid);
-
- if (module.IsWindowsMetadata ())
- WindowsRuntimeProjections.Project (member);
-
return member;
}
diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs
index 3ea1088..4fba786 100644
--- a/Mono.Cecil/AssemblyWriter.cs
+++ b/Mono.Cecil/AssemblyWriter.cs
@@ -1277,6 +1277,8 @@ namespace Mono.Cecil {
void AttachTypeToken (TypeDefinition type)
{
+ var treatment = WindowsRuntimeProjections.RemoveProjection (type);
+
type.token = new MetadataToken (TokenType.TypeDef, type_rid++);
type.fields_range.Start = field_rid;
type.methods_range.Start = method_rid;
@@ -1289,6 +1291,8 @@ namespace Mono.Cecil {
if (type.HasNestedTypes)
AttachNestedTypesToken (type);
+
+ WindowsRuntimeProjections.ApplyProjection (type, treatment);
}
void AttachNestedTypesToken (TypeDefinition type)
@@ -1990,16 +1994,12 @@ namespace Mono.Cecil {
MetadataToken GetMemberRefToken (MemberReference member)
{
- var projection = WindowsRuntimeProjections.RemoveProjection (member);
-
var row = CreateMemberRefRow (member);
MetadataToken token;
if (!member_ref_map.TryGetValue (row, out token))
token = AddMemberReference (member, row);
- WindowsRuntimeProjections.ApplyProjection (member, projection);
-
return token;
}
diff --git a/Mono.Cecil/FieldDefinition.cs b/Mono.Cecil/FieldDefinition.cs
index 242e04e..15b7720 100644
--- a/Mono.Cecil/FieldDefinition.cs
+++ b/Mono.Cecil/FieldDefinition.cs
@@ -68,7 +68,7 @@ namespace Mono.Cecil {
set { offset = value; }
}
- internal new FieldDefinitionProjection WindowsRuntimeProjection {
+ internal FieldDefinitionProjection WindowsRuntimeProjection {
get { return (FieldDefinitionProjection) projection; }
set { projection = value; }
}
diff --git a/Mono.Cecil/GenericParameterResolver.cs b/Mono.Cecil/GenericParameterResolver.cs
new file mode 100644
index 0000000..86525c5
--- /dev/null
+++ b/Mono.Cecil/GenericParameterResolver.cs
@@ -0,0 +1,175 @@
+using Mono.Cecil.Cil;
+using System;
+
+namespace Mono.Cecil {
+ internal sealed class GenericParameterResolver {
+ internal static TypeReference ResolveReturnTypeIfNeeded (MethodReference methodReference)
+ {
+ if (methodReference.DeclaringType.IsArray && methodReference.Name == "Get")
+ return methodReference.ReturnType;
+
+ var genericInstanceMethod = methodReference as GenericInstanceMethod;
+ var declaringGenericInstanceType = methodReference.DeclaringType as GenericInstanceType;
+
+ if (genericInstanceMethod == null && declaringGenericInstanceType == null)
+ return methodReference.ReturnType;
+
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, methodReference.ReturnType);
+ }
+
+ internal static TypeReference ResolveFieldTypeIfNeeded (FieldReference fieldReference)
+ {
+ return ResolveIfNeeded (null, fieldReference.DeclaringType as GenericInstanceType, fieldReference.FieldType);
+ }
+
+ internal static TypeReference ResolveParameterTypeIfNeeded (MethodReference method, ParameterReference parameter)
+ {
+ var genericInstanceMethod = method as GenericInstanceMethod;
+ var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
+
+ if (genericInstanceMethod == null && declaringGenericInstanceType == null)
+ return parameter.ParameterType;
+
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, parameter.ParameterType);
+ }
+
+ internal static TypeReference ResolveVariableTypeIfNeeded (MethodReference method, VariableReference variable)
+ {
+ var genericInstanceMethod = method as GenericInstanceMethod;
+ var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;
+
+ if (genericInstanceMethod == null && declaringGenericInstanceType == null)
+ return variable.VariableType;
+
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, variable.VariableType);
+ }
+
+ private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance declaringGenericInstanceType, TypeReference parameterType)
+ {
+ var byRefType = parameterType as ByReferenceType;
+ if (byRefType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, byRefType);
+
+ var arrayType = parameterType as ArrayType;
+ if (arrayType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, arrayType);
+
+ var genericInstanceType = parameterType as GenericInstanceType;
+ if (genericInstanceType != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericInstanceType);
+
+ var genericParameter = parameterType as GenericParameter;
+ if (genericParameter != null)
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericParameter);
+
+ var requiredModifierType = parameterType as RequiredModifierType;
+ if (requiredModifierType != null && ContainsGenericParameters (requiredModifierType))
+ return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType);
+
+ if (ContainsGenericParameters (parameterType))
+ throw new Exception ("Unexpected generic parameter.");
+
+ return parameterType;
+ }
+
+ private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericParameter genericParameterElement)
+ {
+ return (genericParameterElement.MetadataType == MetadataType.MVar)
+ ? (genericInstanceMethod != null ? genericInstanceMethod.GenericArguments[genericParameterElement.Position] : genericParameterElement)
+ : genericInstanceType.GenericArguments[genericParameterElement.Position];
+ }
+
+ private static ArrayType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ArrayType arrayType)
+ {
+ return new ArrayType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank);
+ }
+
+ private static ByReferenceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType)
+ {
+ return new ByReferenceType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, byReferenceType.ElementType));
+ }
+
+ private static GenericInstanceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1)
+ {
+ if (!ContainsGenericParameters (genericInstanceType1))
+ return genericInstanceType1;
+
+ var newGenericInstance = new GenericInstanceType (genericInstanceType1.ElementType);
+
+ foreach (var genericArgument in genericInstanceType1.GenericArguments) {
+ if (!genericArgument.IsGenericParameter) {
+ newGenericInstance.GenericArguments.Add (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, genericArgument));
+ continue;
+ }
+
+ var genParam = (GenericParameter)genericArgument;
+
+ switch (genParam.Type) {
+ case GenericParameterType.Type: {
+ if (genericInstanceType == null)
+ throw new NotSupportedException ();
+
+ newGenericInstance.GenericArguments.Add (genericInstanceType.GenericArguments[genParam.Position]);
+ }
+ break;
+
+ case GenericParameterType.Method: {
+ if (genericInstanceMethod == null)
+ newGenericInstance.GenericArguments.Add (genParam);
+ else
+ newGenericInstance.GenericArguments.Add (genericInstanceMethod.GenericArguments[genParam.Position]);
+ }
+ break;
+ }
+ }
+
+ return newGenericInstance;
+ }
+
+ private static bool ContainsGenericParameters (TypeReference typeReference)
+ {
+ var genericParameter = typeReference as GenericParameter;
+ if (genericParameter != null)
+ return true;
+
+ var arrayType = typeReference as ArrayType;
+ if (arrayType != null)
+ return ContainsGenericParameters (arrayType.ElementType);
+
+ var pointerType = typeReference as PointerType;
+ if (pointerType != null)
+ return ContainsGenericParameters (pointerType.ElementType);
+
+ var byRefType = typeReference as ByReferenceType;
+ if (byRefType != null)
+ return ContainsGenericParameters (byRefType.ElementType);
+
+ var sentinelType = typeReference as SentinelType;
+ if (sentinelType != null)
+ return ContainsGenericParameters (sentinelType.ElementType);
+
+ var pinnedType = typeReference as PinnedType;
+ if (pinnedType != null)
+ return ContainsGenericParameters (pinnedType.ElementType);
+
+ var requiredModifierType = typeReference as RequiredModifierType;
+ if (requiredModifierType != null)
+ return ContainsGenericParameters (requiredModifierType.ElementType);
+
+ var genericInstance = typeReference as GenericInstanceType;
+ if (genericInstance != null) {
+ foreach (var genericArgument in genericInstance.GenericArguments) {
+ if (ContainsGenericParameters (genericArgument))
+ return true;
+ }
+
+ return false;
+ }
+
+ if (typeReference is TypeSpecification)
+ throw new NotSupportedException ();
+
+ return false;
+ }
+ }
+}
diff --git a/Mono.Cecil/MemberReference.cs b/Mono.Cecil/MemberReference.cs
index 84fd38c..8276a66 100644
--- a/Mono.Cecil/MemberReference.cs
+++ b/Mono.Cecil/MemberReference.cs
@@ -48,11 +48,6 @@ namespace Mono.Cecil {
get { return projection != null; }
}
- internal MemberReferenceProjection WindowsRuntimeProjection {
- get { return (MemberReferenceProjection) projection; }
- set { projection = value; }
- }
-
internal bool HasImage {
get {
var module = Module;
diff --git a/Mono.Cecil/MethodDefinition.cs b/Mono.Cecil/MethodDefinition.cs
index 42bd8f3..b4b88d9 100644
--- a/Mono.Cecil/MethodDefinition.cs
+++ b/Mono.Cecil/MethodDefinition.cs
@@ -81,7 +81,7 @@ namespace Mono.Cecil {
set { sem_attrs = value; }
}
- internal new MethodDefinitionProjection WindowsRuntimeProjection {
+ internal MethodDefinitionProjection WindowsRuntimeProjection {
get { return (MethodDefinitionProjection) projection; }
set { projection = value; }
}
diff --git a/Mono.Cecil/MethodReferenceComparer.cs b/Mono.Cecil/MethodReferenceComparer.cs
new file mode 100644
index 0000000..3bf2c6e
--- /dev/null
+++ b/Mono.Cecil/MethodReferenceComparer.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Cecil {
+ internal sealed class MethodReferenceComparer : EqualityComparer<MethodReference> {
+ // Initialized lazily for each thread
+ [ThreadStatic]
+ static List<MethodReference> xComparisonStack = null;
+
+ [ThreadStatic]
+ static List<MethodReference> yComparisonStack = null;
+
+ public override bool Equals (MethodReference x, MethodReference y)
+ {
+ return AreEqual (x, y);
+ }
+
+ public override int GetHashCode (MethodReference obj)
+ {
+ return GetHashCodeFor (obj);
+ }
+
+ public static bool AreEqual (MethodReference x, MethodReference y)
+ {
+ if (ReferenceEquals (x, y))
+ return true;
+
+ if (x.HasThis != y.HasThis)
+ return false;
+
+ if (x.HasParameters != y.HasParameters)
+ return false;
+
+ if (x.HasGenericParameters != y.HasGenericParameters)
+ return false;
+
+ if (x.Parameters.Count != y.Parameters.Count)
+ return false;
+
+ if (x.Name != y.Name)
+ return false;
+
+ if (!TypeReferenceEqualityComparer.AreEqual (x.DeclaringType, y.DeclaringType))
+ return false;
+
+ var xGeneric = x as GenericInstanceMethod;
+ var yGeneric = y as GenericInstanceMethod;
+ if (xGeneric != null || yGeneric != null) {
+ if (xGeneric == null || yGeneric == null)
+ return false;
+
+ if (xGeneric.GenericArguments.Count != yGeneric.GenericArguments.Count)
+ return false;
+
+ for (int i = 0; i < xGeneric.GenericArguments.Count; i++)
+ if (!TypeReferenceEqualityComparer.AreEqual (xGeneric.GenericArguments[i], yGeneric.GenericArguments[i]))
+ return false;
+ }
+
+ var xResolved = x.Resolve ();
+ var yResolved = y.Resolve ();
+
+ if (xResolved != yResolved)
+ return false;
+
+ if (xResolved == null)
+ {
+ // We couldn't resolve either method. In order for them to be equal, their parameter types _must_ match. But wait, there's a twist!
+ // There exists a situation where we might get into a recursive state: parameter type comparison might lead to comparing the same
+ // methods again if the parameter types are generic parameters whose owners are these methods. We guard against these by using a
+ // thread static list of all our comparisons carried out in the stack so far, and if we're in progress of comparing them already,
+ // we'll just say that they match.
+
+ if (xComparisonStack == null)
+ xComparisonStack = new List<MethodReference> ();
+
+ if (yComparisonStack == null)
+ yComparisonStack = new List<MethodReference> ();
+
+ for (int i = 0; i < xComparisonStack.Count; i++) {
+ if (xComparisonStack[i] == x && yComparisonStack[i] == y)
+ return true;
+ }
+
+ xComparisonStack.Add (x);
+
+ try {
+ yComparisonStack.Add (y);
+
+ try {
+ for (int i = 0; i < x.Parameters.Count; i++) {
+ if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters[i].ParameterType, y.Parameters[i].ParameterType))
+ return false;
+ }
+ } finally {
+ yComparisonStack.RemoveAt (yComparisonStack.Count - 1);
+ }
+ } finally {
+ xComparisonStack.RemoveAt (xComparisonStack.Count - 1);
+ }
+ }
+
+ return true;
+ }
+
+ public static bool AreSignaturesEqual (MethodReference x, MethodReference y, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (x.HasThis != y.HasThis)
+ return false;
+
+ if (x.Parameters.Count != y.Parameters.Count)
+ return false;
+
+ if (x.GenericParameters.Count != y.GenericParameters.Count)
+ return false;
+
+ for (var i = 0; i < x.Parameters.Count; i++)
+ if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters[i].ParameterType, y.Parameters[i].ParameterType, comparisonMode))
+ return false;
+
+ if (!TypeReferenceEqualityComparer.AreEqual (x.ReturnType, y.ReturnType, comparisonMode))
+ return false;
+
+ return true;
+ }
+
+ public static int GetHashCodeFor (MethodReference obj)
+ {
+ // a very good prime number
+ const int hashCodeMultiplier = 486187739;
+
+ var genericInstanceMethod = obj as GenericInstanceMethod;
+ if (genericInstanceMethod != null) {
+ var hashCode = GetHashCodeFor (genericInstanceMethod.ElementMethod);
+ for (var i = 0; i < genericInstanceMethod.GenericArguments.Count; i++)
+ hashCode = hashCode * hashCodeMultiplier + TypeReferenceEqualityComparer.GetHashCodeFor (genericInstanceMethod.GenericArguments[i]);
+ return hashCode;
+ }
+
+ return TypeReferenceEqualityComparer.GetHashCodeFor (obj.DeclaringType) * hashCodeMultiplier + obj.Name.GetHashCode ();
+ }
+ }
+}
diff --git a/Mono.Cecil/Treatments.cs b/Mono.Cecil/Treatments.cs
index 4ceaebf..21c1768 100644
--- a/Mono.Cecil/Treatments.cs
+++ b/Mono.Cecil/Treatments.cs
@@ -23,6 +23,7 @@ namespace Mono.Cecil {
PrefixWindowsRuntimeName = 0x4,
RedirectToClrType = 0x5,
RedirectToClrAttribute = 0x6,
+ RedirectImplementedMethods = 0x7,
Abstract = 0x10,
Internal = 0x20,
@@ -38,7 +39,6 @@ namespace Mono.Cecil {
[Flags]
enum MethodDefinitionTreatment {
None = 0x0,
- Dispose = 0x1,
Abstract = 0x2,
Private = 0x4,
Public = 0x8,
@@ -51,11 +51,6 @@ namespace Mono.Cecil {
Public = 0x1,
}
- enum MemberReferenceTreatment {
- None = 0x0,
- Dispose = 0x1,
- }
-
enum CustomAttributeValueTreatment {
None = 0x0,
AllowSingle = 0x1,
diff --git a/Mono.Cecil/TypeComparisonMode.cs b/Mono.Cecil/TypeComparisonMode.cs
new file mode 100644
index 0000000..f69d98a
--- /dev/null
+++ b/Mono.Cecil/TypeComparisonMode.cs
@@ -0,0 +1,12 @@
+namespace Mono.Cecil
+{
+ internal enum TypeComparisonMode {
+ Exact,
+ SignatureOnly,
+
+ /// <summary>
+ /// Types can be in different assemblies, as long as the module, assembly, and type names match they will be considered equal
+ /// </summary>
+ SignatureOnlyLoose
+ }
+}
diff --git a/Mono.Cecil/TypeReference.cs b/Mono.Cecil/TypeReference.cs
index e3fb5c5..701f83b 100644
--- a/Mono.Cecil/TypeReference.cs
+++ b/Mono.Cecil/TypeReference.cs
@@ -100,7 +100,7 @@ namespace Mono.Cecil {
}
}
- internal new TypeReferenceProjection WindowsRuntimeProjection {
+ internal TypeReferenceProjection WindowsRuntimeProjection {
get { return (TypeReferenceProjection) projection; }
set { projection = value; }
}
diff --git a/Mono.Cecil/TypeReferenceEqualityComparer.cs b/Mono.Cecil/TypeReferenceEqualityComparer.cs
new file mode 100644
index 0000000..29c2ee2
--- /dev/null
+++ b/Mono.Cecil/TypeReferenceEqualityComparer.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Cecil {
+ internal sealed class TypeReferenceEqualityComparer : EqualityComparer<TypeReference> {
+ public override bool Equals (TypeReference x, TypeReference y)
+ {
+ return AreEqual (x, y);
+ }
+
+ public override int GetHashCode (TypeReference obj)
+ {
+ return GetHashCodeFor (obj);
+ }
+
+ public static bool AreEqual (TypeReference a, TypeReference b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ if (a == null || b == null)
+ return false;
+
+ var aMetadataType = a.MetadataType;
+ var bMetadataType = b.MetadataType;
+
+ if (aMetadataType == MetadataType.GenericInstance || bMetadataType == MetadataType.GenericInstance) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericInstanceType)a, (GenericInstanceType)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Array || bMetadataType == MetadataType.Array) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (ArrayType)a;
+ var b1 = (ArrayType)b;
+ if (a1.Rank != b1.Rank)
+ return false;
+
+ return AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Var || bMetadataType == MetadataType.Var) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.MVar || bMetadataType == MetadataType.MVar) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.ByReference || bMetadataType == MetadataType.ByReference) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((ByReferenceType)a).ElementType, ((ByReferenceType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Pointer || bMetadataType == MetadataType.Pointer) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((PointerType)a).ElementType, ((PointerType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.RequiredModifier || bMetadataType == MetadataType.RequiredModifier) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (RequiredModifierType)a;
+ var b1 = (RequiredModifierType)b;
+
+ return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.OptionalModifier || bMetadataType == MetadataType.OptionalModifier) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ var a1 = (OptionalModifierType)a;
+ var b1 = (OptionalModifierType)b;
+
+ return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Pinned || bMetadataType == MetadataType.Pinned) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((PinnedType)a).ElementType, ((PinnedType)b).ElementType, comparisonMode);
+ }
+
+ if (aMetadataType == MetadataType.Sentinel || bMetadataType == MetadataType.Sentinel) {
+ if (aMetadataType != bMetadataType)
+ return false;
+
+ return AreEqual (((SentinelType)a).ElementType, ((SentinelType)b).ElementType, comparisonMode);
+ }
+
+ if (!a.Name.Equals (b.Name) || !a.Namespace.Equals (b.Namespace))
+ return false;
+
+ var xDefinition = a.Resolve ();
+ var yDefinition = b.Resolve ();
+
+ // For loose signature the types could be in different assemblies, as long as the type names match we will consider them equal
+ if (comparisonMode == TypeComparisonMode.SignatureOnlyLoose) {
+ if (xDefinition.Module.Name != yDefinition.Module.Name)
+ return false;
+
+ if (xDefinition.Module.Assembly.Name.Name != yDefinition.Module.Assembly.Name.Name)
+ return false;
+
+ return xDefinition.FullName == yDefinition.FullName;
+ }
+
+ return xDefinition == yDefinition;
+ }
+
+ static bool AreEqual (GenericParameter a, GenericParameter b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ if (a.Position != b.Position)
+ return false;
+
+ if (a.Type != b.Type)
+ return false;
+
+ var aOwnerType = a.Owner as TypeReference;
+ if (aOwnerType != null && AreEqual (aOwnerType, b.Owner as TypeReference, comparisonMode))
+ return true;
+
+ var aOwnerMethod = a.Owner as MethodReference;
+ if (aOwnerMethod != null && comparisonMode != TypeComparisonMode.SignatureOnlyLoose && MethodReferenceComparer.AreEqual (aOwnerMethod, b.Owner as MethodReference))
+ return true;
+
+ return comparisonMode == TypeComparisonMode.SignatureOnly || comparisonMode == TypeComparisonMode.SignatureOnlyLoose;
+ }
+
+ static bool AreEqual (GenericInstanceType a, GenericInstanceType b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact)
+ {
+ if (ReferenceEquals (a, b))
+ return true;
+
+ var aGenericArgumentsCount = a.GenericArguments.Count;
+ if (aGenericArgumentsCount != b.GenericArguments.Count)
+ return false;
+
+ if (!AreEqual (a.ElementType, b.ElementType, comparisonMode))
+ return false;
+
+ for (int i = 0; i < aGenericArgumentsCount; i++)
+ if (!AreEqual (a.GenericArguments[i], b.GenericArguments[i], comparisonMode))
+ return false;
+
+ return true;
+ }
+
+ public static int GetHashCodeFor (TypeReference obj)
+ {
+ // a very good prime number
+ const int hashCodeMultiplier = 486187739;
+ // prime numbers
+ const int genericInstanceTypeMultiplier = 31;
+ const int byReferenceMultiplier = 37;
+ const int pointerMultiplier = 41;
+ const int requiredModifierMultiplier = 43;
+ const int optionalModifierMultiplier = 47;
+ const int pinnedMultiplier = 53;
+ const int sentinelMultiplier = 59;
+
+ var metadataType = obj.MetadataType;
+
+ if (metadataType == MetadataType.GenericInstance) {
+ var genericInstanceType = (GenericInstanceType)obj;
+ var hashCode = GetHashCodeFor (genericInstanceType.ElementType) * hashCodeMultiplier + genericInstanceTypeMultiplier;
+ for (var i = 0; i < genericInstanceType.GenericArguments.Count; i++)
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (genericInstanceType.GenericArguments[i]);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.Array) {
+ var arrayType = (ArrayType)obj;
+ return GetHashCodeFor (arrayType.ElementType) * hashCodeMultiplier + arrayType.Rank.GetHashCode ();
+ }
+
+ if (metadataType == MetadataType.Var || metadataType == MetadataType.MVar) {
+ var genericParameter = (GenericParameter)obj;
+ var hashCode = genericParameter.Position.GetHashCode () * hashCodeMultiplier + ((int)metadataType).GetHashCode ();
+
+ var ownerTypeReference = genericParameter.Owner as TypeReference;
+ if (ownerTypeReference != null)
+ return hashCode * hashCodeMultiplier + GetHashCodeFor (ownerTypeReference);
+
+ var ownerMethodReference = genericParameter.Owner as MethodReference;
+ if (ownerMethodReference != null)
+ return hashCode * hashCodeMultiplier + MethodReferenceComparer.GetHashCodeFor (ownerMethodReference);
+
+ throw new InvalidOperationException ("Generic parameter encountered with invalid owner");
+ }
+
+ if (metadataType == MetadataType.ByReference) {
+ var byReferenceType = (ByReferenceType)obj;
+ return GetHashCodeFor (byReferenceType.ElementType) * hashCodeMultiplier * byReferenceMultiplier;
+ }
+
+ if (metadataType == MetadataType.Pointer) {
+ var pointerType = (PointerType)obj;
+ return GetHashCodeFor (pointerType.ElementType) * hashCodeMultiplier * pointerMultiplier;
+ }
+
+ if (metadataType == MetadataType.RequiredModifier) {
+ var requiredModifierType = (RequiredModifierType)obj;
+ var hashCode = GetHashCodeFor (requiredModifierType.ElementType) * requiredModifierMultiplier;
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (requiredModifierType.ModifierType);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.OptionalModifier) {
+ var optionalModifierType = (OptionalModifierType)obj;
+ var hashCode = GetHashCodeFor (optionalModifierType.ElementType) * optionalModifierMultiplier;
+ hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (optionalModifierType.ModifierType);
+ return hashCode;
+ }
+
+ if (metadataType == MetadataType.Pinned) {
+ var pinnedType = (PinnedType)obj;
+ return GetHashCodeFor (pinnedType.ElementType) * hashCodeMultiplier * pinnedMultiplier;
+ }
+
+ if (metadataType == MetadataType.Sentinel) {
+ var sentinelType = (SentinelType)obj;
+ return GetHashCodeFor (sentinelType.ElementType) * hashCodeMultiplier * sentinelMultiplier;
+ }
+
+ if (metadataType == MetadataType.FunctionPointer) {
+ throw new NotImplementedException ("We currently don't handle function pointer types.");
+ }
+
+ return obj.Namespace.GetHashCode () * hashCodeMultiplier + obj.FullName.GetHashCode ();
+ }
+ }
+}
diff --git a/Mono.Cecil/TypeResolver.cs b/Mono.Cecil/TypeResolver.cs
new file mode 100644
index 0000000..95b0f3a
--- /dev/null
+++ b/Mono.Cecil/TypeResolver.cs
@@ -0,0 +1,220 @@
+using Mono.Cecil.Cil;
+using System;
+
+namespace Mono.Cecil {
+ internal sealed class TypeResolver {
+ private readonly IGenericInstance _typeDefinitionContext;
+ private readonly IGenericInstance _methodDefinitionContext;
+
+ public static TypeResolver For (TypeReference typeReference)
+ {
+ return typeReference.IsGenericInstance ? new TypeResolver ((GenericInstanceType)typeReference) : new TypeResolver ();
+ }
+
+ public static TypeResolver For (TypeReference typeReference, MethodReference methodReference)
+ {
+ return new TypeResolver (typeReference as GenericInstanceType, methodReference as GenericInstanceMethod);
+ }
+
+ public TypeResolver ()
+ {
+
+ }
+
+ public TypeResolver (GenericInstanceType typeDefinitionContext)
+ {
+ _typeDefinitionContext = typeDefinitionContext;
+ }
+
+ public TypeResolver (GenericInstanceMethod methodDefinitionContext)
+ {
+ _methodDefinitionContext = methodDefinitionContext;
+ }
+
+ public TypeResolver (GenericInstanceType typeDefinitionContext, GenericInstanceMethod methodDefinitionContext)
+ {
+ _typeDefinitionContext = typeDefinitionContext;
+ _methodDefinitionContext = methodDefinitionContext;
+ }
+
+ public MethodReference Resolve (MethodReference method)
+ {
+ var methodReference = method;
+ if (IsDummy ())
+ return methodReference;
+
+ var declaringType = Resolve (method.DeclaringType);
+
+ var genericInstanceMethod = method as GenericInstanceMethod;
+ if (genericInstanceMethod != null) {
+ methodReference = new MethodReference (method.Name, method.ReturnType, declaringType);
+
+ foreach (var p in method.Parameters)
+ methodReference.Parameters.Add (new ParameterDefinition (p.Name, p.Attributes, p.ParameterType));
+
+ foreach (var gp in genericInstanceMethod.ElementMethod.GenericParameters)
+ methodReference.GenericParameters.Add (new GenericParameter (gp.Name, methodReference));
+
+ methodReference.HasThis = method.HasThis;
+
+ var m = new GenericInstanceMethod (methodReference);
+ foreach (var ga in genericInstanceMethod.GenericArguments) {
+ m.GenericArguments.Add (Resolve (ga));
+ }
+
+ methodReference = m;
+ } else {
+ methodReference = new MethodReference (method.Name, method.ReturnType, declaringType);
+
+ foreach (var gp in method.GenericParameters)
+ methodReference.GenericParameters.Add (new GenericParameter (gp.Name, methodReference));
+
+ foreach (var p in method.Parameters)
+ methodReference.Parameters.Add (new ParameterDefinition (p.Name, p.Attributes, p.ParameterType));
+
+ methodReference.HasThis = method.HasThis;
+ }
+
+
+ return methodReference;
+ }
+
+ public FieldReference Resolve (FieldReference field)
+ {
+ var declaringType = Resolve (field.DeclaringType);
+
+ if (declaringType == field.DeclaringType)
+ return field;
+
+ return new FieldReference (field.Name, field.FieldType, declaringType);
+ }
+
+ public TypeReference ResolveReturnType (MethodReference method)
+ {
+ return Resolve (GenericParameterResolver.ResolveReturnTypeIfNeeded (method));
+ }
+
+ public TypeReference ResolveParameterType (MethodReference method, ParameterReference parameter)
+ {
+ return Resolve (GenericParameterResolver.ResolveParameterTypeIfNeeded (method, parameter));
+ }
+
+ public TypeReference ResolveVariableType (MethodReference method, VariableReference variable)
+ {
+ return Resolve (GenericParameterResolver.ResolveVariableTypeIfNeeded (method, variable));
+ }
+
+ public TypeReference ResolveFieldType (FieldReference field)
+ {
+ return Resolve (GenericParameterResolver.ResolveFieldTypeIfNeeded (field));
+ }
+
+ public TypeReference Resolve (TypeReference typeReference)
+ {
+ return Resolve (typeReference, true);
+ }
+
+ public TypeReference Resolve (TypeReference typeReference, bool includeTypeDefinitions)
+ {
+ if (IsDummy ())
+ return typeReference;
+
+ if (_typeDefinitionContext != null && _typeDefinitionContext.GenericArguments.Contains (typeReference))
+ return typeReference;
+ if (_methodDefinitionContext != null && _methodDefinitionContext.GenericArguments.Contains (typeReference))
+ return typeReference;
+
+ var genericParameter = typeReference as GenericParameter;
+ if (genericParameter != null) {
+ if (_typeDefinitionContext != null && _typeDefinitionContext.GenericArguments.Contains (genericParameter))
+ return genericParameter;
+ if (_methodDefinitionContext != null && _methodDefinitionContext.GenericArguments.Contains (genericParameter))
+ return genericParameter;
+ return ResolveGenericParameter (genericParameter);
+ }
+
+ var arrayType = typeReference as ArrayType;
+ if (arrayType != null)
+ return new ArrayType (Resolve (arrayType.ElementType), arrayType.Rank);
+
+ var pointerType = typeReference as PointerType;
+ if (pointerType != null)
+ return new PointerType (Resolve (pointerType.ElementType));
+
+ var byReferenceType = typeReference as ByReferenceType;
+ if (byReferenceType != null)
+ return new ByReferenceType (Resolve (byReferenceType.ElementType));
+
+ var pinnedType = typeReference as PinnedType;
+ if (pinnedType != null)
+ return new PinnedType (Resolve (pinnedType.ElementType));
+
+ var genericInstanceType = typeReference as GenericInstanceType;
+ if (genericInstanceType != null) {
+ var newGenericInstanceType = new GenericInstanceType (genericInstanceType.ElementType);
+ foreach (var genericArgument in genericInstanceType.GenericArguments)
+ newGenericInstanceType.GenericArguments.Add (Resolve (genericArgument));
+ return newGenericInstanceType;
+ }
+
+ var requiredModType = typeReference as RequiredModifierType;
+ if (requiredModType != null)
+ return Resolve (requiredModType.ElementType, includeTypeDefinitions);
+
+
+ if (includeTypeDefinitions) {
+ var typeDefinition = typeReference as TypeDefinition;
+ if (typeDefinition != null && typeDefinition.HasGenericParameters) {
+ var newGenericInstanceType = new GenericInstanceType (typeDefinition);
+ foreach (var gp in typeDefinition.GenericParameters)
+ newGenericInstanceType.GenericArguments.Add (Resolve (gp));
+ return newGenericInstanceType;
+ }
+ }
+
+ if (typeReference is TypeSpecification)
+ throw new NotSupportedException (string.Format ("The type {0} cannot be resolved correctly.", typeReference.FullName));
+
+ return typeReference;
+ }
+
+ internal TypeResolver Nested (GenericInstanceMethod genericInstanceMethod)
+ {
+ return new TypeResolver (_typeDefinitionContext as GenericInstanceType, genericInstanceMethod);
+ }
+
+ private TypeReference ResolveGenericParameter (GenericParameter genericParameter)
+ {
+ if (genericParameter.Owner == null)
+ return HandleOwnerlessInvalidILCode (genericParameter);
+
+ var memberReference = genericParameter.Owner as MemberReference;
+ if (memberReference == null)
+ throw new NotSupportedException ();
+
+ return genericParameter.Type == GenericParameterType.Type
+ ? _typeDefinitionContext.GenericArguments[genericParameter.Position]
+ : (_methodDefinitionContext != null ? _methodDefinitionContext.GenericArguments[genericParameter.Position] : genericParameter);
+ }
+
+ private TypeReference HandleOwnerlessInvalidILCode (GenericParameter genericParameter)
+ {
+ // NOTE: If owner is null and we have a method parameter, then we'll assume that the method parameter
+ // is actually a type parameter, and we'll use the type parameter from the corresponding position. I think
+ // this assumption is valid, but if you're visiting this code then I might have been proven wrong.
+ if (genericParameter.Type == GenericParameterType.Method && (_typeDefinitionContext != null && genericParameter.Position < _typeDefinitionContext.GenericArguments.Count))
+ return _typeDefinitionContext.GenericArguments[genericParameter.Position];
+
+ // NOTE: Owner cannot be null, but sometimes the Mono compiler generates invalid IL and we
+ // end up in this situation.
+ // When we do, we assume that the runtime doesn't care about the resolved type of the GenericParameter,
+ // thus we return a reference to System.Object.
+ return genericParameter.Module.TypeSystem.Object;
+ }
+
+ private bool IsDummy ()
+ {
+ return _typeDefinitionContext == null && _methodDefinitionContext == null;
+ }
+ }
+}
diff --git a/Mono.Cecil/WindowsRuntimeProjections.cs b/Mono.Cecil/WindowsRuntimeProjections.cs
index 5ecd53c..946116b 100644
--- a/Mono.Cecil/WindowsRuntimeProjections.cs
+++ b/Mono.Cecil/WindowsRuntimeProjections.cs
@@ -15,29 +15,21 @@ using Mono.Collections.Generic;
namespace Mono.Cecil {
- sealed class MemberReferenceProjection {
-
- public readonly string Name;
- public readonly MemberReferenceTreatment Treatment;
-
- public MemberReferenceProjection (MemberReference member, MemberReferenceTreatment treatment)
- {
- Name = member.Name;
- Treatment = treatment;
- }
- }
-
sealed class TypeDefinitionProjection {
public readonly TypeAttributes Attributes;
public readonly string Name;
public readonly TypeDefinitionTreatment Treatment;
+ public readonly Collection<MethodDefinition> RedirectedMethods;
+ public readonly Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> RedirectedInterfaces;
- public TypeDefinitionProjection (TypeDefinition type, TypeDefinitionTreatment treatment)
+ public TypeDefinitionProjection (TypeDefinition type, TypeDefinitionTreatment treatment, Collection<MethodDefinition> redirectedMethods, Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces)
{
Attributes = type.Attributes;
Name = type.Name;
Treatment = treatment;
+ RedirectedMethods = redirectedMethods;
+ RedirectedInterfaces = redirectedInterfaces;
}
}
@@ -106,16 +98,14 @@ namespace Mono.Cecil {
public readonly string ClrName;
public readonly string ClrAssembly;
public readonly bool Attribute;
- public readonly bool Disposable;
- public ProjectionInfo (string winrt_namespace, string clr_namespace, string clr_name, string clr_assembly, bool attribute = false, bool disposable = false)
+ public ProjectionInfo (string winrt_namespace, string clr_namespace, string clr_name, string clr_assembly, bool attribute = false)
{
WinRTNamespace = winrt_namespace;
ClrNamespace = clr_namespace;
ClrName = clr_name;
ClrAssembly = clr_assembly;
Attribute = attribute;
- Disposable = disposable;
}
}
@@ -163,7 +153,7 @@ namespace Mono.Cecil {
{ "HResult", new ProjectionInfo ("Windows.Foundation", "System", "Exception", "System.Runtime") },
{ "IBindableIterable", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IEnumerable", "System.Runtime") },
{ "IBindableVector", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IList", "System.Runtime") },
- { "IClosable", new ProjectionInfo ("Windows.Foundation", "System", "IDisposable", "System.Runtime", disposable: true) },
+ { "IClosable", new ProjectionInfo ("Windows.Foundation", "System", "IDisposable", "System.Runtime") },
{ "ICommand", new ProjectionInfo ("Windows.UI.Xaml.Input", "System.Windows.Input", "ICommand", "System.ObjectModel") },
{ "IIterable`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IEnumerable`1", "System.Runtime") },
{ "IKeyValuePair`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "KeyValuePair`2", "System.Runtime") },
@@ -229,21 +219,24 @@ namespace Mono.Cecil {
{
var treatment = TypeDefinitionTreatment.None;
var metadata_kind = type.Module.MetadataKind;
+ Collection<MethodDefinition> redirectedMethods = null;
+ Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces = null;
if (type.IsWindowsRuntime) {
if (metadata_kind == MetadataKind.WindowsMetadata) {
treatment = GetWellKnownTypeDefinitionTreatment (type);
if (treatment != TypeDefinitionTreatment.None) {
- ApplyProjection (type, new TypeDefinitionProjection (type, treatment));
+ ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces));
return;
}
var base_type = type.BaseType;
- if (base_type != null && IsAttribute (base_type))
+ if (base_type != null && IsAttribute (base_type)) {
treatment = TypeDefinitionTreatment.NormalAttribute;
- else
- treatment = TypeDefinitionTreatment.NormalType;
- }
+ } else {
+ treatment = GenerateRedirectionInformation (type, out redirectedMethods, out redirectedInterfaces);
+ }
+ }
else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && NeedsWindowsRuntimePrefix (type))
treatment = TypeDefinitionTreatment.PrefixWindowsRuntimeName;
@@ -255,7 +248,7 @@ namespace Mono.Cecil {
treatment = TypeDefinitionTreatment.UnmangleWindowsRuntimeName;
if (treatment != TypeDefinitionTreatment.None)
- ApplyProjection (type, new TypeDefinitionProjection (type, treatment));
+ ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces));
}
static TypeDefinitionTreatment GetWellKnownTypeDefinitionTreatment (TypeDefinition type)
@@ -275,6 +268,106 @@ namespace Mono.Cecil {
return TypeDefinitionTreatment.None;
}
+ private static TypeDefinitionTreatment GenerateRedirectionInformation (TypeDefinition type, out Collection<MethodDefinition> redirectedMethods, out Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces)
+ {
+ bool implementsProjectedInterface = false;
+ redirectedMethods = null;
+ redirectedInterfaces = null;
+
+ foreach (var implementedInterface in type.Interfaces) {
+ if (IsRedirectedType (implementedInterface.InterfaceType)) {
+ implementsProjectedInterface = true;
+ break;
+ }
+ }
+
+ if (!implementsProjectedInterface)
+ return TypeDefinitionTreatment.NormalType;
+
+ var allImplementedInterfaces = new HashSet<TypeReference> (new TypeReferenceEqualityComparer ());
+ redirectedMethods = new Collection<MethodDefinition> ();
+ redirectedInterfaces = new Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> ();
+
+ foreach (var @interface in type.Interfaces) {
+ var interfaceType = @interface.InterfaceType;
+
+ if (IsRedirectedType (interfaceType)) {
+ allImplementedInterfaces.Add (interfaceType);
+ CollectImplementedInterfaces (interfaceType, allImplementedInterfaces);
+ }
+ }
+
+ foreach (var implementedInterface in type.Interfaces) {
+ var interfaceType = implementedInterface.InterfaceType;
+ if (IsRedirectedType (implementedInterface.InterfaceType)) {
+ var etype = interfaceType.GetElementType ();
+ var unprojectedType = new TypeReference (etype.Namespace, etype.Name, etype.Module, etype.Scope) {
+ DeclaringType = etype.DeclaringType,
+ projection = etype.projection
+ };
+
+ RemoveProjection (unprojectedType);
+
+ var genericInstanceType = interfaceType as GenericInstanceType;
+ if (genericInstanceType != null) {
+ var genericUnprojectedType = new GenericInstanceType (unprojectedType);
+ foreach (var genericArgument in genericInstanceType.GenericArguments)
+ genericUnprojectedType.GenericArguments.Add (genericArgument);
+
+ unprojectedType = genericUnprojectedType;
+ }
+
+ var unprojectedInterface = new InterfaceImplementation (unprojectedType);
+ redirectedInterfaces.Add (new KeyValuePair<InterfaceImplementation, InterfaceImplementation> (implementedInterface, unprojectedInterface));
+ }
+ }
+
+ // Interfaces don't inherit methods of the interfaces they implement
+ if (!type.IsInterface) {
+ foreach (var implementedInterface in allImplementedInterfaces) {
+ RedirectInterfaceMethods (implementedInterface, redirectedMethods);
+ }
+ }
+
+ return TypeDefinitionTreatment.RedirectImplementedMethods;
+ }
+
+ private static void CollectImplementedInterfaces (TypeReference type, HashSet<TypeReference> results)
+ {
+ var typeResolver = TypeResolver.For (type);
+ var typeDef = type.Resolve ();
+
+ foreach (var implementedInterface in typeDef.Interfaces) {
+ var interfaceType = typeResolver.Resolve (implementedInterface.InterfaceType);
+ results.Add (interfaceType);
+ CollectImplementedInterfaces (interfaceType, results);
+ }
+ }
+
+ private static void RedirectInterfaceMethods (TypeReference interfaceType, Collection<MethodDefinition> redirectedMethods)
+ {
+ var typeResolver = TypeResolver.For (interfaceType);
+ var typeDef = interfaceType.Resolve ();
+
+ foreach (var method in typeDef.Methods) {
+ var redirectedMethod = new MethodDefinition (method.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot, typeResolver.Resolve (method.ReturnType));
+ redirectedMethod.ImplAttributes = MethodImplAttributes.Runtime;
+
+ foreach (var parameter in method.Parameters) {
+ redirectedMethod.Parameters.Add (new ParameterDefinition (parameter.Name, parameter.Attributes, typeResolver.Resolve (parameter.ParameterType)));
+ }
+
+ redirectedMethod.Overrides.Add (typeResolver.Resolve (method));
+ redirectedMethods.Add (redirectedMethod);
+ }
+ }
+
+ private static bool IsRedirectedType (TypeReference type)
+ {
+ var typeRefProjection = type.GetElementType ().projection as TypeReferenceProjection;
+ return typeRefProjection != null && typeRefProjection.Treatment == TypeReferenceTreatment.UseProjectionInfo;
+ }
+
static bool NeedsWindowsRuntimePrefix (TypeDefinition type)
{
if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.Interface)) != TypeAttributes.Public)
@@ -336,6 +429,32 @@ namespace Mono.Cecil {
case TypeDefinitionTreatment.RedirectToClrAttribute:
type.Attributes = type.Attributes & ~TypeAttributes.Public;
break;
+
+ case TypeDefinitionTreatment.RedirectImplementedMethods: {
+ type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import;
+
+ foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) {
+ type.Interfaces.Add (redirectedInterfacePair.Value);
+
+ foreach (var customAttribute in redirectedInterfacePair.Key.CustomAttributes)
+ redirectedInterfacePair.Value.CustomAttributes.Add (customAttribute);
+
+ redirectedInterfacePair.Key.CustomAttributes.Clear ();
+
+ foreach (var method in type.Methods) {
+ foreach (var @override in method.Overrides) {
+ if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Key.InterfaceType)) {
+ @override.DeclaringType = redirectedInterfacePair.Value.InterfaceType;
+ }
+ }
+ }
+ }
+
+ foreach (var method in projection.RedirectedMethods) {
+ type.Methods.Add (method);
+ }
+ }
+ break;
}
if ((treatment & TypeDefinitionTreatment.Abstract) != 0)
@@ -358,6 +477,28 @@ namespace Mono.Cecil {
type.Attributes = projection.Attributes;
type.Name = projection.Name;
+ if (projection.Treatment == TypeDefinitionTreatment.RedirectImplementedMethods) {
+ foreach (var method in projection.RedirectedMethods) {
+ type.Methods.Remove (method);
+ }
+
+ foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) {
+ foreach (var method in type.Methods) {
+ foreach (var @override in method.Overrides) {
+ if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Value.InterfaceType)) {
+ @override.DeclaringType = redirectedInterfacePair.Key.InterfaceType;
+ }
+ }
+ }
+
+ foreach (var customAttribute in redirectedInterfacePair.Value.CustomAttributes)
+ redirectedInterfacePair.Key.CustomAttributes.Add (customAttribute);
+
+ redirectedInterfacePair.Value.CustomAttributes.Clear ();
+ type.Interfaces.Remove (redirectedInterfacePair.Value);
+ }
+ }
+
return projection;
}
@@ -482,27 +623,16 @@ namespace Mono.Cecil {
{
var seen_redirected = false;
var seen_non_redirected = false;
- var disposable = false;
- foreach (var @override in method.Overrides)
- {
- if (@override.MetadataToken.TokenType == TokenType.MemberRef && ImplementsRedirectedInterface (@override, out disposable))
- {
+ foreach (var @override in method.Overrides) {
+ if (@override.MetadataToken.TokenType == TokenType.MemberRef && ImplementsRedirectedInterface (@override)) {
seen_redirected = true;
- if (disposable)
- break;
- }
- else
+ } else {
seen_non_redirected = true;
+ }
}
- if (disposable)
- {
- treatment = MethodDefinitionTreatment.Dispose;
- other = false;
- }
- else if (seen_redirected && !seen_non_redirected)
- {
+ if (seen_redirected && !seen_non_redirected) {
treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall | MethodDefinitionTreatment.Private;
other = false;
}
@@ -540,9 +670,6 @@ namespace Mono.Cecil {
var treatment = projection.Treatment;
- if ((treatment & MethodDefinitionTreatment.Dispose) != 0)
- method.Name = "Dispose";
-
if ((treatment & MethodDefinitionTreatment.Abstract) != 0)
method.Attributes |= MethodAttributes.Abstract;
@@ -615,19 +742,8 @@ namespace Mono.Cecil {
return projection;
}
- public static void Project (MemberReference member)
+ static bool ImplementsRedirectedInterface (MemberReference member)
{
- bool disposable;
- if (!ImplementsRedirectedInterface (member, out disposable) || !disposable)
- return;
-
- ApplyProjection (member, new MemberReferenceProjection (member, MemberReferenceTreatment.Dispose));
- }
-
- static bool ImplementsRedirectedInterface (MemberReference member, out bool disposable)
- {
- disposable = false;
-
var declaring_type = member.DeclaringType;
TypeReference type;
switch (declaring_type.MetadataToken.TokenType) {
@@ -655,7 +771,6 @@ namespace Mono.Cecil {
ProjectionInfo info;
if (Projections.TryGetValue (type.Name, out info) && type.Namespace == info.WinRTNamespace) {
- disposable = info.Disposable;
found = true;
}
@@ -664,29 +779,6 @@ namespace Mono.Cecil {
return found;
}
- public static void ApplyProjection (MemberReference member, MemberReferenceProjection projection)
- {
- if (projection == null)
- return;
-
- if (projection.Treatment == MemberReferenceTreatment.Dispose)
- member.Name = "Dispose";
-
- member.WindowsRuntimeProjection = projection;
- }
-
- public static MemberReferenceProjection RemoveProjection (MemberReference member)
- {
- if (!member.IsWindowsRuntimeProjection)
- return null;
-
- var projection = member.WindowsRuntimeProjection;
- member.WindowsRuntimeProjection = null;
-
- member.Name = projection.Name;
-
- return projection;
- }
public void AddVirtualReferences (Collection<AssemblyNameReference> references)
{
diff --git a/Test/Mono.Cecil.Tests/LoadAssemblyDefinitionForTestsBaseSimple.cs b/Test/Mono.Cecil.Tests/LoadAssemblyDefinitionForTestsBaseSimple.cs
new file mode 100644
index 0000000..5c3b713
--- /dev/null
+++ b/Test/Mono.Cecil.Tests/LoadAssemblyDefinitionForTestsBaseSimple.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+
+namespace Mono.Cecil.Tests {
+
+ public class LoadAssemblyDefinitionForTestsBaseSimple {
+
+ protected AssemblyDefinition _assembly;
+ protected AssemblyDefinition _mscorlib;
+
+ public void SetupAssemblyDefinitions (Assembly testAssembly)
+ {
+ _assembly = AssemblyDefinition.ReadAssembly (testAssembly.Location);
+ _mscorlib = _assembly.MainModule.TypeSystem.Object.Resolve ().Module.Assembly;
+ }
+ }
+}
diff --git a/Test/Mono.Cecil.Tests/MethodReferenceComparerTests.cs b/Test/Mono.Cecil.Tests/MethodReferenceComparerTests.cs
new file mode 100644
index 0000000..92e5de3
--- /dev/null
+++ b/Test/Mono.Cecil.Tests/MethodReferenceComparerTests.cs
@@ -0,0 +1,135 @@
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Mono.Cecil.Tests {
+
+ [TestFixture]
+ public class MethodReferenceComparerTests : LoadAssemblyDefinitionForTestsBaseSimple {
+
+ private TypeDefinition _class1;
+ private TypeDefinition _class2;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ SetupAssemblyDefinitions (typeof (MethodReferenceComparerTests).Assembly);
+ _class1 = TypeDefinitionUtils.TypeDefinitionFor (typeof (Class1), _assembly);
+ _class2 = TypeDefinitionUtils.TypeDefinitionFor (typeof (Class2), _assembly);
+ }
+
+ [Test]
+ public void MethodReferenceEqualsMethodDefinition ()
+ {
+ var typeDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+ var method = typeDefinition.Methods.Single (m => m.Name == "GetHashCode");
+ var methodReference = new MethodReference (method.Name, method.ReturnType, method.DeclaringType);
+ methodReference.HasThis = method.HasThis;
+
+ Assert.That (MethodReferenceComparer.AreEqual (method, methodReference), Is.True);
+ }
+
+ [Test]
+ public void VerifyMethodSignatureMatches ()
+ {
+ Assert.IsTrue (CompareSignatures ("MethodWithNoParametersOrReturn"));
+ Assert.IsTrue (CompareSignatures ("GenericMethodWithNoParametersOrReturn"));
+ Assert.IsFalse (CompareSignatures ("MethodWithNoParametersOrReturn", "GenericMethodWithNoParametersOrReturn"));
+
+ Assert.IsTrue (CompareSignatures ("MethodWithIntParameterAndVoidReturn"));
+ }
+
+ [Test]
+ public void VerifySignatureComparisonConsidersStatic ()
+ {
+ Assert.IsTrue (CompareSignatures ("StaticMethodWithNoParametersOrReturn"));
+ Assert.IsTrue (CompareSignatures ("StaticMethodWithNoParametersOrReturn"));
+ Assert.IsFalse (CompareSignatures ("MethodWithNoParametersOrReturn", "StaticMethodWithNoParametersOrReturn"));
+ Assert.IsFalse (CompareSignatures ("GenericMethodWithNoParametersOrReturn", "GenericStaticMethodWithNoParametersOrReturn"));
+ }
+
+ [Test]
+ public void VerifyMethodSignatureWithGenericParameters ()
+ {
+ Assert.IsTrue (CompareSignatures ("GenericMethodWithGenericParameter"));
+ Assert.IsTrue (CompareSignatures ("GenericMethodWithGenericParameterArray"));
+ Assert.IsTrue (CompareSignatures ("GenericMethodWithByReferenceGenericParameter"));
+ Assert.IsTrue (CompareSignatures ("GenericMethodWithGenericInstanceGenericParameter"));
+ }
+
+ [Test]
+ public void VerifyNonResolvableMethodReferencesWithDifferentParameterTypesAreNotEqual ()
+ {
+ var method1 = new MethodReference ("TestMethod", _class1.Module.TypeSystem.Void, _class1);
+ method1.Parameters.Add (new ParameterDefinition (new ByReferenceType (_class1.Module.TypeSystem.Int16)));
+
+ var method2 = new MethodReference ("TestMethod", _class1.Module.TypeSystem.Void, _class1);
+ method2.Parameters.Add (new ParameterDefinition (new ByReferenceType (_class1.Module.TypeSystem.Char)));
+
+ Assert.IsFalse (MethodReferenceComparer.AreEqual (method1, method2));
+ }
+
+ [Test]
+ public void VerifyNonResolvableRecursiveMethodsDontStackOverflow ()
+ {
+ var method1 = new MethodReference ("TestMethod", _class1.Module.TypeSystem.Void, _class1);
+ method1.GenericParameters.Add (new GenericParameter (method1));
+ method1.Parameters.Add (new ParameterDefinition (method1.GenericParameters[0]));
+
+ var method2 = new MethodReference ("TestMethod", _class1.Module.TypeSystem.Void, _class1);
+ method2.GenericParameters.Add (new GenericParameter (method2));
+ method2.Parameters.Add (new ParameterDefinition (method2.GenericParameters[0]));
+
+ Assert.IsTrue (MethodReferenceComparer.AreEqual (method1, method2));
+ }
+
+ bool CompareSignatures (string name)
+ {
+ return CompareSignatures (name, name);
+ }
+
+ bool CompareSignatures (string name1, string name2)
+ {
+ return MethodReferenceComparer.AreSignaturesEqual (GetMethod (_class1, name1), GetMethod (_class2, name2), TypeComparisonMode.SignatureOnly);
+ }
+
+ static MethodDefinition GetMethod (TypeDefinition type, string name)
+ {
+ return type.Methods.Single (m => m.Name == name);
+ }
+
+ class GenericClass<T> {
+
+ }
+
+ class Class1 {
+
+ void MethodWithNoParametersOrReturn () {}
+ void GenericMethodWithNoParametersOrReturn<T> () {}
+ static void StaticMethodWithNoParametersOrReturn () {}
+ static void GenericStaticMethodWithNoParametersOrReturn<T> () {}
+
+ void MethodWithIntParameterAndVoidReturn (int a) {}
+
+ void GenericMethodWithGenericParameter<T> (T t) {}
+ void GenericMethodWithGenericParameterArray<T> (T[] t) {}
+ void GenericMethodWithByReferenceGenericParameter<T> (ref T a) {}
+ void GenericMethodWithGenericInstanceGenericParameter<T> (GenericClass<T> a) {}
+ }
+
+ class Class2 {
+
+ void MethodWithNoParametersOrReturn () {}
+ void GenericMethodWithNoParametersOrReturn<T> () {}
+ static void StaticMethodWithNoParametersOrReturn () {}
+ static void GenericStaticMethodWithNoParametersOrReturn<T> () {}
+
+ void MethodWithIntParameterAndVoidReturn (int a) {}
+
+ void GenericMethodWithGenericParameter<T> (T t) {}
+ void GenericMethodWithGenericParameterArray<T> (T[] t) {}
+ void GenericMethodWithByReferenceGenericParameter<T> (ref T a) {}
+ void GenericMethodWithGenericInstanceGenericParameter<T> (GenericClass<T> a) {}
+ }
+ }
+}
diff --git a/Test/Mono.Cecil.Tests/TypeDefinitionUtils.cs b/Test/Mono.Cecil.Tests/TypeDefinitionUtils.cs
new file mode 100644
index 0000000..7324584
--- /dev/null
+++ b/Test/Mono.Cecil.Tests/TypeDefinitionUtils.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Cecil {
+
+ public static class TypeDefinitionUtils {
+
+ public static TypeReference TypeDefinitionForGeneric (
+ Type genericType, AssemblyDefinition genericAssemblyDefinition,
+ Type paramterType, AssemblyDefinition parameterAssemblyDefinition)
+ {
+ var paramDefinition = TypeDefinitionUtils.TypeDefinitionFor (paramterType, parameterAssemblyDefinition);
+ var genericDefinition = TypeDefinitionUtils.TypeDefinitionFor (genericType, genericAssemblyDefinition);
+ var genericInstance = new GenericInstanceType (genericDefinition);
+ genericInstance.GenericArguments.Add (paramDefinition);
+ return genericInstance;
+ }
+
+ public static TypeDefinition TypeDefinitionFor (Type type, AssemblyDefinition assemblyDefinition)
+ {
+ var stack = new Stack<string> ();
+ var currentType = type;
+ while (currentType != null) {
+ stack.Push ( (currentType.DeclaringType == null ? currentType.Namespace + "." : "") + currentType.Name);
+ currentType = currentType.DeclaringType;
+ }
+
+ var typeDefinition = assemblyDefinition.MainModule.GetType (stack.Pop ());
+ if (typeDefinition == null)
+ return null;
+
+ while (stack.Count > 0) {
+ var name = stack.Pop ();
+ typeDefinition = typeDefinition.NestedTypes.Single (t => t.Name == name);
+ }
+
+ return typeDefinition;
+ }
+ }
+}
diff --git a/Test/Mono.Cecil.Tests/TypeReferenceComparisonTests.cs b/Test/Mono.Cecil.Tests/TypeReferenceComparisonTests.cs
new file mode 100644
index 0000000..d8332eb
--- /dev/null
+++ b/Test/Mono.Cecil.Tests/TypeReferenceComparisonTests.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace Mono.Cecil.Tests {
+
+ [TestFixture]
+ public class TypeReferenceComparisonTests : LoadAssemblyDefinitionForTestsBaseSimple {
+
+ [SetUp]
+ public void SetUp ()
+ {
+ SetupAssemblyDefinitions (typeof (TypeReferenceComparisonTests).Assembly);
+ }
+
+ [Test]
+ public void TypeReferenceEqualsTypeDefinition ()
+ {
+ var typeDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+ var typeReference = new TypeReference (typeDefinition.Namespace, typeDefinition.Name, typeDefinition.Module, typeDefinition.Scope);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (typeDefinition, typeReference), Is.True);
+ }
+
+ [Test]
+ public void GenericParametersFromTwoTypesAreNotEqual ()
+ {
+ var listDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (List<>), _mscorlib);
+ var stackDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Comparer<>), _mscorlib);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (listDefinition.GenericParameters[0], stackDefinition.GenericParameters[0]), Is.False);
+ }
+
+ [Test]
+ public void ArrayTypesDoNotMatchIfRankIsDifferent ()
+ {
+ var elementType = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (new ArrayType (elementType, 1), new ArrayType (elementType, 2)), Is.False, "Two array types with different ranks match, which is not expected.");
+ }
+
+ [Test]
+ public void ArrayTypesDoNotMatchIfElementTypeIsDifferent ()
+ {
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (new ArrayType (TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib), 1), new ArrayType (TypeDefinitionUtils.TypeDefinitionFor (typeof (Int64), _mscorlib), 1)), Is.False, "Two array types with different element types match, which is not expected.");
+ }
+
+ [Test]
+ public void ArrayTypesWithDifferentRanksToNotMatch ()
+ {
+ var elementType = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual ( (TypeSpecification) new ArrayType (elementType, 1), (TypeSpecification) new ArrayType (elementType, 2)), Is.False, "Two type specifications that are array types with different ranks match, which is not expected.");
+ }
+
+ [Test]
+ public void GenericInstanceTypeFromTwoTypesAreNotEqual ()
+ {
+ var int32Definition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+ var listDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (List<>), _mscorlib);
+ var listGenericInstance = new GenericInstanceType (listDefinition);
+ listGenericInstance.GenericArguments.Add (int32Definition);
+ var stackDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Comparer<>), _mscorlib);
+ var stackGenericInstance = new GenericInstanceType (stackDefinition);
+ stackGenericInstance.GenericArguments.Add (int32Definition);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (listGenericInstance, stackGenericInstance), Is.False);
+ }
+
+ [Test]
+ public void GenericInstanceTypeForSameTypeIsEqual ()
+ {
+ var int32Definition = TypeDefinitionUtils.TypeDefinitionFor (typeof (Int32), _mscorlib);
+ var listDefinition = TypeDefinitionUtils.TypeDefinitionFor (typeof (List<>), _mscorlib);
+ var listGenericInstance = new GenericInstanceType (listDefinition);
+ listGenericInstance.GenericArguments.Add (int32Definition);
+ var listGenericInstance2 = new GenericInstanceType (listDefinition);
+ listGenericInstance2.GenericArguments.Add (int32Definition);
+
+ Assert.That (TypeReferenceEqualityComparer.AreEqual (listGenericInstance, listGenericInstance2), Is.True);
+ }
+ }
+}
diff --git a/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs b/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
index 9b10fd5..bac85cf 100644
--- a/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
+++ b/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
@@ -8,8 +8,10 @@ using System.Linq;
using System.Text;
namespace Mono.Cecil.Tests {
+
[TestFixture]
public abstract class BaseWindowsRuntimeProjectionsTests : BaseTestFixture {
+
protected abstract string ModuleName { get; }
protected abstract MetadataKind ExpectedMetadataKind { get; }
protected abstract string [] ManagedClassTypeNames { get; }
@@ -96,6 +98,7 @@ namespace Mono.Cecil.Tests {
[TestFixture]
public class ManagedWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjectionsTests {
+
protected override string ModuleName { get { return "ManagedWinmd.winmd"; } }
protected override MetadataKind ExpectedMetadataKind { get { return MetadataKind.ManagedWindowsMetadata; } }
@@ -132,6 +135,7 @@ namespace Mono.Cecil.Tests {
[TestFixture]
public class NativeWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjectionsTests {
+
protected override string ModuleName { get { return "NativeWinmd.winmd"; } }
protected override MetadataKind ExpectedMetadataKind { get { return MetadataKind.WindowsMetadata; } }
@@ -139,6 +143,146 @@ namespace Mono.Cecil.Tests {
protected override string [] ManagedClassTypeNames { get { return new [] { "ManagedClass" }; } }
protected override string [] CustomListTypeNames { get { return new [] { "CustomList" }; } }
+
+ [Test]
+ public void CanProjectAndRedirectInterfaces ()
+ {
+ if (Platform.OnMono)
+ return;
+
+ TestModule (ModuleName, (module) => {
+ var customListClass = module.Types.Single (t => t.Name == "CustomList");
+ Assert.AreEqual (5, customListClass.Interfaces.Count);
+
+ Assert.AreEqual (1, customListClass.Interfaces[0].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Metadata.DefaultAttribute", customListClass.Interfaces[0].CustomAttributes[0].AttributeType.FullName);
+ Assert.AreEqual ("NativeWinmd.__ICustomListPublicNonVirtuals", customListClass.Interfaces[0].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customListClass.Interfaces[1].CustomAttributes.Count);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<System.Int32>", customListClass.Interfaces[1].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customListClass.Interfaces[2].CustomAttributes.Count);
+ Assert.AreEqual ("System.Collections.Generic.IEnumerable`1<System.Int32>", customListClass.Interfaces[2].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customListClass.Interfaces[3].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IVector`1<System.Int32>", customListClass.Interfaces[3].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customListClass.Interfaces[4].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IIterable`1<System.Int32>", customListClass.Interfaces[4].InterfaceType.FullName);
+
+ var customPropertySetClass = module.Types.Single (t => t.Name == "CustomPropertySet");
+ Assert.AreEqual (7, customPropertySetClass.Interfaces.Count);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[0].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IPropertySet", customPropertySetClass.Interfaces[0].InterfaceType.FullName);
+
+ Assert.AreEqual (1, customPropertySetClass.Interfaces[1].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Metadata.DefaultAttribute", customPropertySetClass.Interfaces[1].CustomAttributes[0].AttributeType.FullName);
+ Assert.AreEqual ("NativeWinmd.__ICustomPropertySetPublicNonVirtuals", customPropertySetClass.Interfaces[1].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[2].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IObservableMap`2<System.String,System.Object>", customPropertySetClass.Interfaces[2].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[3].CustomAttributes.Count);
+ Assert.AreEqual ("System.Collections.Generic.IDictionary`2<System.String,System.Object>", customPropertySetClass.Interfaces[3].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[4].CustomAttributes.Count);
+ Assert.AreEqual ("System.Collections.Generic.IEnumerable`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Object>>", customPropertySetClass.Interfaces[4].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[5].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IMap`2<System.String,System.Object>", customPropertySetClass.Interfaces[5].InterfaceType.FullName);
+
+ Assert.AreEqual (0, customPropertySetClass.Interfaces[6].CustomAttributes.Count);
+ Assert.AreEqual ("Windows.Foundation.Collections.IIterable`1<System.Collections.Generic.KeyValuePair`2<System.String,System.Object>>", customPropertySetClass.Interfaces[6].InterfaceType.FullName);
+
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }
+
+ [Test]
+ public void CanProjectInterfaceMethods ()
+ {
+ if (Platform.OnMono)
+ return;
+
+ TestModule (ModuleName, (module) => {
+ var customListClass = module.Types.Single (t => t.Name == "CustomList");
+ Assert.AreEqual (28, customListClass.Methods.Count);
+ Assert.AreEqual (TypeDefinitionTreatment.RedirectImplementedMethods, customListClass.WindowsRuntimeProjection.Treatment);
+
+ // Verify that projections add implementations for all projected interfaces methods
+ Assert.AreEqual (customListClass.Methods[0].FullName, "System.Void NativeWinmd.CustomList::.ctor()");
+ Assert.AreEqual (customListClass.Methods[1].FullName, "Windows.Foundation.Collections.IIterator`1<System.Int32> NativeWinmd.CustomList::First()");
+ Assert.AreEqual (customListClass.Methods[2].FullName, "System.UInt32 NativeWinmd.CustomList::get_Size()");
+ Assert.AreEqual (customListClass.Methods[3].FullName, "System.Int32 NativeWinmd.CustomList::GetAt(System.UInt32)");
+ Assert.AreEqual (customListClass.Methods[4].FullName, "System.Collections.Generic.IReadOnlyList`1<System.Int32> NativeWinmd.CustomList::GetView()");
+ Assert.AreEqual (customListClass.Methods[5].FullName, "System.Boolean NativeWinmd.CustomList::IndexOf(System.Int32,System.UInt32&)");
+ Assert.AreEqual (customListClass.Methods[6].FullName, "System.Void NativeWinmd.CustomList::SetAt(System.UInt32,System.Int32)");
+ Assert.AreEqual (customListClass.Methods[7].FullName, "System.Void NativeWinmd.CustomList::InsertAt(System.UInt32,System.Int32)");
+ Assert.AreEqual (customListClass.Methods[8].FullName, "System.Void NativeWinmd.CustomList::RemoveAt(System.UInt32)");
+ Assert.AreEqual (customListClass.Methods[9].FullName, "System.Void NativeWinmd.CustomList::Append(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[10].FullName, "System.Void NativeWinmd.CustomList::RemoveAtEnd()");
+ Assert.AreEqual (customListClass.Methods[11].FullName, "System.Void NativeWinmd.CustomList::Clear()");
+ Assert.AreEqual (customListClass.Methods[12].FullName, "System.UInt32 NativeWinmd.CustomList::GetMany(System.UInt32,System.Int32[])");
+ Assert.AreEqual (customListClass.Methods[13].FullName, "System.Void NativeWinmd.CustomList::ReplaceAll(System.Int32[])");
+ Assert.AreEqual (customListClass.Methods[14].FullName, "System.Int32 NativeWinmd.CustomList::get_Item(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[15].FullName, "System.Void NativeWinmd.CustomList::set_Item(System.Int32,System.Int32)");
+ Assert.AreEqual (customListClass.Methods[16].FullName, "System.Int32 NativeWinmd.CustomList::IndexOf(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[17].FullName, "System.Void NativeWinmd.CustomList::Insert(System.Int32,System.Int32)");
+ Assert.AreEqual (customListClass.Methods[18].FullName, "System.Void NativeWinmd.CustomList::RemoveAt(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[19].FullName, "System.Int32 NativeWinmd.CustomList::get_Count()");
+ Assert.AreEqual (customListClass.Methods[20].FullName, "System.Boolean NativeWinmd.CustomList::get_IsReadOnly()");
+ Assert.AreEqual (customListClass.Methods[21].FullName, "System.Void NativeWinmd.CustomList::Add(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[22].FullName, "System.Void NativeWinmd.CustomList::Clear()");
+ Assert.AreEqual (customListClass.Methods[23].FullName, "System.Boolean NativeWinmd.CustomList::Contains(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[24].FullName, "System.Void NativeWinmd.CustomList::CopyTo(System.Int32[],System.Int32)");
+ Assert.AreEqual (customListClass.Methods[25].FullName, "System.Boolean NativeWinmd.CustomList::Remove(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[26].FullName, "System.Collections.Generic.IEnumerator`1<System.Int32> NativeWinmd.CustomList::GetEnumerator()");
+ Assert.AreEqual (customListClass.Methods[27].FullName, "System.Collections.IEnumerator NativeWinmd.CustomList::GetEnumerator()");
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }
+
+ [Test]
+ public void CanProjectMethodOverrides ()
+ {
+ if (Platform.OnMono)
+ return;
+
+ TestModule (ModuleName, (module) => {
+ var customListClass = module.Types.Single (t => t.Name == "CustomList");
+
+ for (int i = 1; i < customListClass.Methods.Count; i++)
+ Assert.AreEqual (1, customListClass.Methods[i].Overrides.Count);
+
+ Assert.AreEqual (customListClass.Methods[1].Overrides[0].FullName, "Windows.Foundation.Collections.IIterator`1<!0> Windows.Foundation.Collections.IIterable`1<System.Int32>::First()");
+ Assert.AreEqual (customListClass.Methods[2].Overrides[0].FullName, "System.UInt32 Windows.Foundation.Collections.IVector`1<System.Int32>::get_Size()");
+ Assert.AreEqual (customListClass.Methods[3].Overrides[0].FullName, "!0 Windows.Foundation.Collections.IVector`1<System.Int32>::GetAt(System.UInt32)");
+ Assert.AreEqual (customListClass.Methods[4].Overrides[0].FullName, "System.Collections.Generic.IReadOnlyList`1<!0> Windows.Foundation.Collections.IVector`1<System.Int32>::GetView()");
+ Assert.AreEqual (customListClass.Methods[5].Overrides[0].FullName, "System.Boolean Windows.Foundation.Collections.IVector`1<System.Int32>::IndexOf(!0,System.UInt32&)");
+ Assert.AreEqual (customListClass.Methods[6].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::SetAt(System.UInt32,!0)");
+ Assert.AreEqual (customListClass.Methods[7].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::InsertAt(System.UInt32,!0)");
+ Assert.AreEqual (customListClass.Methods[8].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::RemoveAt(System.UInt32)");
+ Assert.AreEqual (customListClass.Methods[9].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::Append(!0)");
+ Assert.AreEqual (customListClass.Methods[10].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::RemoveAtEnd()");
+ Assert.AreEqual (customListClass.Methods[11].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::Clear()");
+ Assert.AreEqual (customListClass.Methods[12].Overrides[0].FullName, "System.UInt32 Windows.Foundation.Collections.IVector`1<System.Int32>::GetMany(System.UInt32,!0[])");
+ Assert.AreEqual (customListClass.Methods[13].Overrides[0].FullName, "System.Void Windows.Foundation.Collections.IVector`1<System.Int32>::ReplaceAll(!0[])");
+ Assert.AreEqual (customListClass.Methods[14].Overrides[0].FullName, "T System.Collections.Generic.IList`1<System.Int32>::get_Item(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[15].Overrides[0].FullName, "System.Void System.Collections.Generic.IList`1<System.Int32>::set_Item(System.Int32,T)");
+ Assert.AreEqual (customListClass.Methods[16].Overrides[0].FullName, "System.Int32 System.Collections.Generic.IList`1<System.Int32>::IndexOf(T)");
+ Assert.AreEqual (customListClass.Methods[17].Overrides[0].FullName, "System.Void System.Collections.Generic.IList`1<System.Int32>::Insert(System.Int32,T)");
+ Assert.AreEqual (customListClass.Methods[18].Overrides[0].FullName, "System.Void System.Collections.Generic.IList`1<System.Int32>::RemoveAt(System.Int32)");
+ Assert.AreEqual (customListClass.Methods[19].Overrides[0].FullName, "System.Int32 System.Collections.Generic.ICollection`1<System.Int32>::get_Count()");
+ Assert.AreEqual (customListClass.Methods[20].Overrides[0].FullName, "System.Boolean System.Collections.Generic.ICollection`1<System.Int32>::get_IsReadOnly()");
+ Assert.AreEqual (customListClass.Methods[21].Overrides[0].FullName, "System.Void System.Collections.Generic.ICollection`1<System.Int32>::Add(T)");
+ Assert.AreEqual (customListClass.Methods[22].Overrides[0].FullName, "System.Void System.Collections.Generic.ICollection`1<System.Int32>::Clear()");
+ Assert.AreEqual (customListClass.Methods[23].Overrides[0].FullName, "System.Boolean System.Collections.Generic.ICollection`1<System.Int32>::Contains(T)");
+ Assert.AreEqual (customListClass.Methods[24].Overrides[0].FullName, "System.Void System.Collections.Generic.ICollection`1<System.Int32>::CopyTo(T[],System.Int32)");
+ Assert.AreEqual (customListClass.Methods[25].Overrides[0].FullName, "System.Boolean System.Collections.Generic.ICollection`1<System.Int32>::Remove(T)");
+ Assert.AreEqual (customListClass.Methods[26].Overrides[0].FullName, "System.Collections.Generic.IEnumerator`1<T> System.Collections.Generic.IEnumerable`1<System.Int32>::GetEnumerator()");
+ Assert.AreEqual (customListClass.Methods[27].Overrides[0].FullName, "System.Collections.IEnumerator System.Collections.IEnumerable::GetEnumerator()");
+
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }
}
}
#endif
diff --git a/Test/Resources/assemblies/NativeWinmd.winmd b/Test/Resources/assemblies/NativeWinmd.winmd
index 53fedff..b6417cf 100644
--- a/Test/Resources/assemblies/NativeWinmd.winmd
+++ b/Test/Resources/assemblies/NativeWinmd.winmd
Binary files differ