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:
authorMarek Safar <marek.safar@gmail.com>2020-09-26 15:34:01 +0300
committerMarek Safar <marek.safar@gmail.com>2020-09-26 15:34:01 +0300
commit831dd0a964e510c4f2f484a0b411ed320ad4634b (patch)
treed63030eee5949e760c447b01dc3d6a3a26076757 /Mono.Cecil
parent75fc419764f239dcdd679657316e6eae31e04dc2 (diff)
parente9a4815fdb102a3bc87a606c6e9ee5f61c00414a (diff)
Merge remote-tracking branch 'upstream/master' into master
Diffstat (limited to 'Mono.Cecil')
-rw-r--r--Mono.Cecil/AssemblyReader.cs6
-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
13 files changed, 982 insertions, 101 deletions
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index 3dae1e4..ffefbcc 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -419,7 +419,7 @@ namespace Mono.Cecil {
for (int i = 0; i < methods.Count; i++) {
var method = methods [i];
- if (method.HasBody && method.token.RID != 0 && method.debug_info == null)
+ if (method.HasBody && method.token.RID != 0 && (method.debug_info == null || !method.debug_info.HasSequencePoints))
method.debug_info = symbol_reader.Read (method);
}
}
@@ -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 b359ddf..41b53ae 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)
@@ -1996,16 +2000,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)
{