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:
Diffstat (limited to 'Mono.Cecil/WindowsRuntimeProjections.cs')
-rw-r--r--Mono.Cecil/WindowsRuntimeProjections.cs248
1 files changed, 170 insertions, 78 deletions
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)
{