WindowsRuntimeProjections.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Threading;
  13. using ILRuntime.Mono.Collections.Generic;
  14. namespace ILRuntime.Mono.Cecil {
  15. sealed class TypeDefinitionProjection {
  16. public readonly TypeAttributes Attributes;
  17. public readonly string Name;
  18. public readonly TypeDefinitionTreatment Treatment;
  19. public readonly Collection<MethodDefinition> RedirectedMethods;
  20. public readonly Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> RedirectedInterfaces;
  21. public TypeDefinitionProjection(TypeDefinition type, TypeDefinitionTreatment treatment, Collection<MethodDefinition> redirectedMethods, Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces)
  22. {
  23. Attributes = type.Attributes;
  24. Name = type.Name;
  25. Treatment = treatment;
  26. RedirectedMethods = redirectedMethods;
  27. RedirectedInterfaces = redirectedInterfaces;
  28. }
  29. }
  30. sealed class TypeReferenceProjection {
  31. public readonly string Name;
  32. public readonly string Namespace;
  33. public readonly IMetadataScope Scope;
  34. public readonly TypeReferenceTreatment Treatment;
  35. public TypeReferenceProjection (TypeReference type, TypeReferenceTreatment treatment)
  36. {
  37. Name = type.Name;
  38. Namespace = type.Namespace;
  39. Scope = type.Scope;
  40. Treatment = treatment;
  41. }
  42. }
  43. sealed class MethodDefinitionProjection {
  44. public readonly MethodAttributes Attributes;
  45. public readonly MethodImplAttributes ImplAttributes;
  46. public readonly string Name;
  47. public readonly MethodDefinitionTreatment Treatment;
  48. public MethodDefinitionProjection (MethodDefinition method, MethodDefinitionTreatment treatment)
  49. {
  50. Attributes = method.Attributes;
  51. ImplAttributes = method.ImplAttributes;
  52. Name = method.Name;
  53. Treatment = treatment;
  54. }
  55. }
  56. sealed class FieldDefinitionProjection {
  57. public readonly FieldAttributes Attributes;
  58. public readonly FieldDefinitionTreatment Treatment;
  59. public FieldDefinitionProjection (FieldDefinition field, FieldDefinitionTreatment treatment)
  60. {
  61. Attributes = field.Attributes;
  62. Treatment = treatment;
  63. }
  64. }
  65. sealed class CustomAttributeValueProjection {
  66. public readonly AttributeTargets Targets;
  67. public readonly CustomAttributeValueTreatment Treatment;
  68. public CustomAttributeValueProjection (AttributeTargets targets, CustomAttributeValueTreatment treatment)
  69. {
  70. Targets = targets;
  71. Treatment = treatment;
  72. }
  73. }
  74. sealed class WindowsRuntimeProjections {
  75. struct ProjectionInfo {
  76. public readonly string WinRTNamespace;
  77. public readonly string ClrNamespace;
  78. public readonly string ClrName;
  79. public readonly string ClrAssembly;
  80. public readonly bool Attribute;
  81. public ProjectionInfo (string winrt_namespace, string clr_namespace, string clr_name, string clr_assembly, bool attribute = false)
  82. {
  83. WinRTNamespace = winrt_namespace;
  84. ClrNamespace = clr_namespace;
  85. ClrName = clr_name;
  86. ClrAssembly = clr_assembly;
  87. Attribute = attribute;
  88. }
  89. }
  90. static readonly Version version = new Version (4, 0, 0, 0);
  91. static readonly byte[] contract_pk_token = {
  92. 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A
  93. };
  94. static readonly byte[] contract_pk = {
  95. 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00,
  96. 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
  97. 0x07, 0xD1, 0xFA, 0x57, 0xC4, 0xAE, 0xD9, 0xF0, 0xA3, 0x2E, 0x84, 0xAA, 0x0F, 0xAE, 0xFD, 0x0D,
  98. 0xE9, 0xE8, 0xFD, 0x6A, 0xEC, 0x8F, 0x87, 0xFB, 0x03, 0x76, 0x6C, 0x83, 0x4C, 0x99, 0x92, 0x1E,
  99. 0xB2, 0x3B, 0xE7, 0x9A, 0xD9, 0xD5, 0xDC, 0xC1, 0xDD, 0x9A, 0xD2, 0x36, 0x13, 0x21, 0x02, 0x90,
  100. 0x0B, 0x72, 0x3C, 0xF9, 0x80, 0x95, 0x7F, 0xC4, 0xE1, 0x77, 0x10, 0x8F, 0xC6, 0x07, 0x77, 0x4F,
  101. 0x29, 0xE8, 0x32, 0x0E, 0x92, 0xEA, 0x05, 0xEC, 0xE4, 0xE8, 0x21, 0xC0, 0xA5, 0xEF, 0xE8, 0xF1,
  102. 0x64, 0x5C, 0x4C, 0x0C, 0x93, 0xC1, 0xAB, 0x99, 0x28, 0x5D, 0x62, 0x2C, 0xAA, 0x65, 0x2C, 0x1D,
  103. 0xFA, 0xD6, 0x3D, 0x74, 0x5D, 0x6F, 0x2D, 0xE5, 0xF1, 0x7E, 0x5E, 0xAF, 0x0F, 0xC4, 0x96, 0x3D,
  104. 0x26, 0x1C, 0x8A, 0x12, 0x43, 0x65, 0x18, 0x20, 0x6D, 0xC0, 0x93, 0x34, 0x4D, 0x5A, 0xD2, 0x93
  105. };
  106. static Dictionary<string, ProjectionInfo> projections;
  107. static Dictionary<string, ProjectionInfo> Projections
  108. {
  109. get {
  110. if (projections != null)
  111. return projections;
  112. var new_projections = new Dictionary<string, ProjectionInfo> {
  113. { "AttributeTargets", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeTargets", "System.Runtime") },
  114. { "AttributeUsageAttribute", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeUsageAttribute", "System.Runtime", attribute: true) },
  115. { "Color", new ProjectionInfo ("Windows.UI", "Windows.UI", "Color", "System.Runtime.WindowsRuntime") },
  116. { "CornerRadius", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "CornerRadius", "System.Runtime.WindowsRuntime.UI.Xaml") },
  117. { "DateTime", new ProjectionInfo ("Windows.Foundation", "System", "DateTimeOffset", "System.Runtime") },
  118. { "Duration", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Duration", "System.Runtime.WindowsRuntime.UI.Xaml") },
  119. { "DurationType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "DurationType", "System.Runtime.WindowsRuntime.UI.Xaml") },
  120. { "EventHandler`1", new ProjectionInfo ("Windows.Foundation", "System", "EventHandler`1", "System.Runtime") },
  121. { "EventRegistrationToken", new ProjectionInfo ("Windows.Foundation", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime") },
  122. { "GeneratorPosition", new ProjectionInfo ("Windows.UI.Xaml.Controls.Primitives", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "System.Runtime.WindowsRuntime.UI.Xaml") },
  123. { "GridLength", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridLength", "System.Runtime.WindowsRuntime.UI.Xaml") },
  124. { "GridUnitType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridUnitType", "System.Runtime.WindowsRuntime.UI.Xaml") },
  125. { "HResult", new ProjectionInfo ("Windows.Foundation", "System", "Exception", "System.Runtime") },
  126. { "IBindableIterable", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IEnumerable", "System.Runtime") },
  127. { "IBindableVector", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IList", "System.Runtime") },
  128. { "IClosable", new ProjectionInfo ("Windows.Foundation", "System", "IDisposable", "System.Runtime") },
  129. { "ICommand", new ProjectionInfo ("Windows.UI.Xaml.Input", "System.Windows.Input", "ICommand", "System.ObjectModel") },
  130. { "IIterable`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IEnumerable`1", "System.Runtime") },
  131. { "IKeyValuePair`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "KeyValuePair`2", "System.Runtime") },
  132. { "IMapView`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyDictionary`2", "System.Runtime") },
  133. { "IMap`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IDictionary`2", "System.Runtime") },
  134. { "INotifyCollectionChanged", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "INotifyCollectionChanged", "System.ObjectModel") },
  135. { "INotifyPropertyChanged", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "INotifyPropertyChanged", "System.ObjectModel") },
  136. { "IReference`1", new ProjectionInfo ("Windows.Foundation", "System", "Nullable`1", "System.Runtime") },
  137. { "IVectorView`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyList`1", "System.Runtime") },
  138. { "IVector`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IList`1", "System.Runtime") },
  139. { "KeyTime", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "KeyTime", "System.Runtime.WindowsRuntime.UI.Xaml") },
  140. { "Matrix", new ProjectionInfo ("Windows.UI.Xaml.Media", "Windows.UI.Xaml.Media", "Matrix", "System.Runtime.WindowsRuntime.UI.Xaml") },
  141. { "Matrix3D", new ProjectionInfo ("Windows.UI.Xaml.Media.Media3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", "System.Runtime.WindowsRuntime.UI.Xaml") },
  142. { "Matrix3x2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix3x2", "System.Numerics.Vectors") },
  143. { "Matrix4x4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix4x4", "System.Numerics.Vectors") },
  144. { "NotifyCollectionChangedAction", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedAction", "System.ObjectModel") },
  145. { "NotifyCollectionChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", "System.ObjectModel") },
  146. { "NotifyCollectionChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", "System.ObjectModel") },
  147. { "Plane", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Plane", "System.Numerics.Vectors") },
  148. { "Point", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Point", "System.Runtime.WindowsRuntime") },
  149. { "PropertyChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventArgs", "System.ObjectModel") },
  150. { "PropertyChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventHandler", "System.ObjectModel") },
  151. { "Quaternion", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Quaternion", "System.Numerics.Vectors") },
  152. { "Rect", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Rect", "System.Runtime.WindowsRuntime") },
  153. { "RepeatBehavior", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "System.Runtime.WindowsRuntime.UI.Xaml") },
  154. { "RepeatBehaviorType", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "System.Runtime.WindowsRuntime.UI.Xaml") },
  155. { "Size", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Size", "System.Runtime.WindowsRuntime") },
  156. { "Thickness", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Thickness", "System.Runtime.WindowsRuntime.UI.Xaml") },
  157. { "TimeSpan", new ProjectionInfo ("Windows.Foundation", "System", "TimeSpan", "System.Runtime") },
  158. { "TypeName", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System", "Type", "System.Runtime") },
  159. { "Uri", new ProjectionInfo ("Windows.Foundation", "System", "Uri", "System.Runtime") },
  160. { "Vector2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector2", "System.Numerics.Vectors") },
  161. { "Vector3", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector3", "System.Numerics.Vectors") },
  162. { "Vector4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector4", "System.Numerics.Vectors") },
  163. };
  164. Interlocked.CompareExchange (ref projections, new_projections, null);
  165. return projections;
  166. }
  167. }
  168. readonly ModuleDefinition module;
  169. Version corlib_version = new Version (255, 255, 255, 255);
  170. AssemblyNameReference[] virtual_references;
  171. AssemblyNameReference[] VirtualReferences {
  172. get {
  173. if (virtual_references == null) {
  174. // force module to read its assembly references. that will in turn initialize virtual_references
  175. Mixin.Read (module.AssemblyReferences);
  176. }
  177. return virtual_references;
  178. }
  179. }
  180. public WindowsRuntimeProjections (ModuleDefinition module)
  181. {
  182. this.module = module;
  183. }
  184. public static void Project (TypeDefinition type)
  185. {
  186. var treatment = TypeDefinitionTreatment.None;
  187. var metadata_kind = type.Module.MetadataKind;
  188. Collection<MethodDefinition> redirectedMethods = null;
  189. Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces = null;
  190. if (type.IsWindowsRuntime) {
  191. if (metadata_kind == MetadataKind.WindowsMetadata) {
  192. treatment = GetWellKnownTypeDefinitionTreatment (type);
  193. if (treatment != TypeDefinitionTreatment.None) {
  194. ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces));
  195. return;
  196. }
  197. var base_type = type.BaseType;
  198. if (base_type != null && IsAttribute (base_type)) {
  199. treatment = TypeDefinitionTreatment.NormalAttribute;
  200. } else {
  201. treatment = GenerateRedirectionInformation (type, out redirectedMethods, out redirectedInterfaces);
  202. }
  203. }
  204. else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && NeedsWindowsRuntimePrefix (type))
  205. treatment = TypeDefinitionTreatment.PrefixWindowsRuntimeName;
  206. if (treatment == TypeDefinitionTreatment.PrefixWindowsRuntimeName || treatment == TypeDefinitionTreatment.NormalType)
  207. if (!type.IsInterface && HasAttribute (type, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute"))
  208. treatment |= TypeDefinitionTreatment.Abstract;
  209. }
  210. else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && IsClrImplementationType (type))
  211. treatment = TypeDefinitionTreatment.UnmangleWindowsRuntimeName;
  212. if (treatment != TypeDefinitionTreatment.None)
  213. ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces));
  214. }
  215. static TypeDefinitionTreatment GetWellKnownTypeDefinitionTreatment (TypeDefinition type)
  216. {
  217. ProjectionInfo info;
  218. if (!Projections.TryGetValue (type.Name, out info))
  219. return TypeDefinitionTreatment.None;
  220. var treatment = info.Attribute ? TypeDefinitionTreatment.RedirectToClrAttribute : TypeDefinitionTreatment.RedirectToClrType;
  221. if (type.Namespace == info.ClrNamespace)
  222. return treatment;
  223. if (type.Namespace == info.WinRTNamespace)
  224. return treatment | TypeDefinitionTreatment.Internal;
  225. return TypeDefinitionTreatment.None;
  226. }
  227. private static TypeDefinitionTreatment GenerateRedirectionInformation (TypeDefinition type, out Collection<MethodDefinition> redirectedMethods, out Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> redirectedInterfaces)
  228. {
  229. bool implementsProjectedInterface = false;
  230. redirectedMethods = null;
  231. redirectedInterfaces = null;
  232. foreach (var implementedInterface in type.Interfaces) {
  233. if (IsRedirectedType (implementedInterface.InterfaceType)) {
  234. implementsProjectedInterface = true;
  235. break;
  236. }
  237. }
  238. if (!implementsProjectedInterface)
  239. return TypeDefinitionTreatment.NormalType;
  240. var allImplementedInterfaces = new HashSet<TypeReference> (new TypeReferenceEqualityComparer ());
  241. redirectedMethods = new Collection<MethodDefinition> ();
  242. redirectedInterfaces = new Collection<KeyValuePair<InterfaceImplementation, InterfaceImplementation>> ();
  243. foreach (var @interface in type.Interfaces) {
  244. var interfaceType = @interface.InterfaceType;
  245. if (IsRedirectedType (interfaceType)) {
  246. allImplementedInterfaces.Add (interfaceType);
  247. CollectImplementedInterfaces (interfaceType, allImplementedInterfaces);
  248. }
  249. }
  250. foreach (var implementedInterface in type.Interfaces) {
  251. var interfaceType = implementedInterface.InterfaceType;
  252. if (IsRedirectedType (implementedInterface.InterfaceType)) {
  253. var etype = interfaceType.GetElementType ();
  254. var unprojectedType = new TypeReference (etype.Namespace, etype.Name, etype.Module, etype.Scope) {
  255. DeclaringType = etype.DeclaringType,
  256. projection = etype.projection
  257. };
  258. RemoveProjection (unprojectedType);
  259. var genericInstanceType = interfaceType as GenericInstanceType;
  260. if (genericInstanceType != null) {
  261. var genericUnprojectedType = new GenericInstanceType (unprojectedType);
  262. foreach (var genericArgument in genericInstanceType.GenericArguments)
  263. genericUnprojectedType.GenericArguments.Add (genericArgument);
  264. unprojectedType = genericUnprojectedType;
  265. }
  266. var unprojectedInterface = new InterfaceImplementation (unprojectedType);
  267. redirectedInterfaces.Add (new KeyValuePair<InterfaceImplementation, InterfaceImplementation> (implementedInterface, unprojectedInterface));
  268. }
  269. }
  270. // Interfaces don't inherit methods of the interfaces they implement
  271. if (!type.IsInterface) {
  272. foreach (var implementedInterface in allImplementedInterfaces) {
  273. RedirectInterfaceMethods (implementedInterface, redirectedMethods);
  274. }
  275. }
  276. return TypeDefinitionTreatment.RedirectImplementedMethods;
  277. }
  278. private static void CollectImplementedInterfaces (TypeReference type, HashSet<TypeReference> results)
  279. {
  280. var typeResolver = TypeResolver.For (type);
  281. var typeDef = type.Resolve ();
  282. foreach (var implementedInterface in typeDef.Interfaces) {
  283. var interfaceType = typeResolver.Resolve (implementedInterface.InterfaceType);
  284. results.Add (interfaceType);
  285. CollectImplementedInterfaces (interfaceType, results);
  286. }
  287. }
  288. private static void RedirectInterfaceMethods (TypeReference interfaceType, Collection<MethodDefinition> redirectedMethods)
  289. {
  290. var typeResolver = TypeResolver.For (interfaceType);
  291. var typeDef = interfaceType.Resolve ();
  292. foreach (var method in typeDef.Methods) {
  293. var redirectedMethod = new MethodDefinition (method.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot, typeResolver.Resolve (method.ReturnType));
  294. redirectedMethod.ImplAttributes = MethodImplAttributes.Runtime;
  295. foreach (var parameter in method.Parameters) {
  296. redirectedMethod.Parameters.Add (new ParameterDefinition (parameter.Name, parameter.Attributes, typeResolver.Resolve (parameter.ParameterType)));
  297. }
  298. redirectedMethod.Overrides.Add (typeResolver.Resolve (method));
  299. redirectedMethods.Add (redirectedMethod);
  300. }
  301. }
  302. private static bool IsRedirectedType (TypeReference type)
  303. {
  304. var typeRefProjection = type.GetElementType ().projection as TypeReferenceProjection;
  305. return typeRefProjection != null && typeRefProjection.Treatment == TypeReferenceTreatment.UseProjectionInfo;
  306. }
  307. static bool NeedsWindowsRuntimePrefix (TypeDefinition type)
  308. {
  309. if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.Interface)) != TypeAttributes.Public)
  310. return false;
  311. var base_type = type.BaseType;
  312. if (base_type == null || base_type.MetadataToken.TokenType != TokenType.TypeRef)
  313. return false;
  314. if (base_type.Namespace == "System")
  315. switch (base_type.Name)
  316. {
  317. case "Attribute":
  318. case "MulticastDelegate":
  319. case "ValueType":
  320. return false;
  321. }
  322. return true;
  323. }
  324. static bool IsClrImplementationType (TypeDefinition type)
  325. {
  326. if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.SpecialName)) != TypeAttributes.SpecialName)
  327. return false;
  328. return type.Name.StartsWith ("<CLR>");
  329. }
  330. public static void ApplyProjection (TypeDefinition type, TypeDefinitionProjection projection)
  331. {
  332. if (projection == null)
  333. return;
  334. var treatment = projection.Treatment;
  335. switch (treatment & TypeDefinitionTreatment.KindMask) {
  336. case TypeDefinitionTreatment.NormalType:
  337. type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import;
  338. break;
  339. case TypeDefinitionTreatment.NormalAttribute:
  340. type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Sealed;
  341. break;
  342. case TypeDefinitionTreatment.UnmangleWindowsRuntimeName:
  343. type.Attributes = type.Attributes & ~TypeAttributes.SpecialName | TypeAttributes.Public;
  344. type.Name = type.Name.Substring ("<CLR>".Length);
  345. break;
  346. case TypeDefinitionTreatment.PrefixWindowsRuntimeName:
  347. type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import;
  348. type.Name = "<WinRT>" + type.Name;
  349. break;
  350. case TypeDefinitionTreatment.RedirectToClrType:
  351. type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import;
  352. break;
  353. case TypeDefinitionTreatment.RedirectToClrAttribute:
  354. type.Attributes = type.Attributes & ~TypeAttributes.Public;
  355. break;
  356. case TypeDefinitionTreatment.RedirectImplementedMethods: {
  357. type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import;
  358. foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) {
  359. type.Interfaces.Add (redirectedInterfacePair.Value);
  360. foreach (var customAttribute in redirectedInterfacePair.Key.CustomAttributes)
  361. redirectedInterfacePair.Value.CustomAttributes.Add (customAttribute);
  362. redirectedInterfacePair.Key.CustomAttributes.Clear ();
  363. foreach (var method in type.Methods) {
  364. foreach (var @override in method.Overrides) {
  365. if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Key.InterfaceType)) {
  366. @override.DeclaringType = redirectedInterfacePair.Value.InterfaceType;
  367. }
  368. }
  369. }
  370. }
  371. foreach (var method in projection.RedirectedMethods) {
  372. type.Methods.Add (method);
  373. }
  374. }
  375. break;
  376. }
  377. if ((treatment & TypeDefinitionTreatment.Abstract) != 0)
  378. type.Attributes |= TypeAttributes.Abstract;
  379. if ((treatment & TypeDefinitionTreatment.Internal) != 0)
  380. type.Attributes &= ~TypeAttributes.Public;
  381. type.WindowsRuntimeProjection = projection;
  382. }
  383. public static TypeDefinitionProjection RemoveProjection (TypeDefinition type)
  384. {
  385. if (!type.IsWindowsRuntimeProjection)
  386. return null;
  387. var projection = type.WindowsRuntimeProjection;
  388. type.WindowsRuntimeProjection = null;
  389. type.Attributes = projection.Attributes;
  390. type.Name = projection.Name;
  391. if (projection.Treatment == TypeDefinitionTreatment.RedirectImplementedMethods) {
  392. foreach (var method in projection.RedirectedMethods) {
  393. type.Methods.Remove (method);
  394. }
  395. foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) {
  396. foreach (var method in type.Methods) {
  397. foreach (var @override in method.Overrides) {
  398. if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Value.InterfaceType)) {
  399. @override.DeclaringType = redirectedInterfacePair.Key.InterfaceType;
  400. }
  401. }
  402. }
  403. foreach (var customAttribute in redirectedInterfacePair.Value.CustomAttributes)
  404. redirectedInterfacePair.Key.CustomAttributes.Add (customAttribute);
  405. redirectedInterfacePair.Value.CustomAttributes.Clear ();
  406. type.Interfaces.Remove (redirectedInterfacePair.Value);
  407. }
  408. }
  409. return projection;
  410. }
  411. public static void Project (TypeReference type)
  412. {
  413. TypeReferenceTreatment treatment;
  414. ProjectionInfo info;
  415. if (Projections.TryGetValue (type.Name, out info) && info.WinRTNamespace == type.Namespace)
  416. treatment = TypeReferenceTreatment.UseProjectionInfo;
  417. else
  418. treatment = GetSpecialTypeReferenceTreatment (type);
  419. if (treatment != TypeReferenceTreatment.None)
  420. ApplyProjection (type, new TypeReferenceProjection (type, treatment));
  421. }
  422. static TypeReferenceTreatment GetSpecialTypeReferenceTreatment (TypeReference type)
  423. {
  424. if (type.Namespace == "System") {
  425. if (type.Name == "MulticastDelegate")
  426. return TypeReferenceTreatment.SystemDelegate;
  427. if (type.Name == "Attribute")
  428. return TypeReferenceTreatment.SystemAttribute;
  429. }
  430. return TypeReferenceTreatment.None;
  431. }
  432. static bool IsAttribute (TypeReference type)
  433. {
  434. if (type.MetadataToken.TokenType != TokenType.TypeRef)
  435. return false;
  436. return type.Name == "Attribute" && type.Namespace == "System";
  437. }
  438. static bool IsEnum (TypeReference type)
  439. {
  440. if (type.MetadataToken.TokenType != TokenType.TypeRef)
  441. return false;
  442. return type.Name == "Enum" && type.Namespace == "System";
  443. }
  444. public static void ApplyProjection (TypeReference type, TypeReferenceProjection projection)
  445. {
  446. if (projection == null)
  447. return;
  448. switch (projection.Treatment)
  449. {
  450. case TypeReferenceTreatment.SystemDelegate:
  451. case TypeReferenceTreatment.SystemAttribute:
  452. type.Scope = type.Module.Projections.GetAssemblyReference ("System.Runtime");
  453. break;
  454. case TypeReferenceTreatment.UseProjectionInfo:
  455. var info = Projections [type.Name];
  456. type.Name = info.ClrName;
  457. type.Namespace = info.ClrNamespace;
  458. type.Scope = type.Module.Projections.GetAssemblyReference (info.ClrAssembly);
  459. break;
  460. }
  461. type.WindowsRuntimeProjection = projection;
  462. }
  463. public static TypeReferenceProjection RemoveProjection (TypeReference type)
  464. {
  465. if (!type.IsWindowsRuntimeProjection)
  466. return null;
  467. var projection = type.WindowsRuntimeProjection;
  468. type.WindowsRuntimeProjection = null;
  469. type.Name = projection.Name;
  470. type.Namespace = projection.Namespace;
  471. type.Scope = projection.Scope;
  472. return projection;
  473. }
  474. public static void Project (MethodDefinition method)
  475. {
  476. var treatment = MethodDefinitionTreatment.None;
  477. var other = false;
  478. var declaring_type = method.DeclaringType;
  479. if (declaring_type.IsWindowsRuntime)
  480. {
  481. if (IsClrImplementationType (declaring_type))
  482. treatment = MethodDefinitionTreatment.None;
  483. else if (declaring_type.IsNested)
  484. treatment = MethodDefinitionTreatment.None;
  485. else if (declaring_type.IsInterface)
  486. treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall;
  487. else if (declaring_type.Module.MetadataKind == MetadataKind.ManagedWindowsMetadata && !method.IsPublic)
  488. treatment = MethodDefinitionTreatment.None;
  489. else
  490. {
  491. other = true;
  492. var base_type = declaring_type.BaseType;
  493. if (base_type != null && base_type.MetadataToken.TokenType == TokenType.TypeRef)
  494. {
  495. switch (GetSpecialTypeReferenceTreatment(base_type))
  496. {
  497. case TypeReferenceTreatment.SystemDelegate:
  498. treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.Public;
  499. other = false;
  500. break;
  501. case TypeReferenceTreatment.SystemAttribute:
  502. treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall;
  503. other = false;
  504. break;
  505. }
  506. }
  507. }
  508. }
  509. if (other)
  510. {
  511. var seen_redirected = false;
  512. var seen_non_redirected = false;
  513. foreach (var @override in method.Overrides) {
  514. if (@override.MetadataToken.TokenType == TokenType.MemberRef && ImplementsRedirectedInterface (@override)) {
  515. seen_redirected = true;
  516. } else {
  517. seen_non_redirected = true;
  518. }
  519. }
  520. if (seen_redirected && !seen_non_redirected) {
  521. treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall | MethodDefinitionTreatment.Private;
  522. other = false;
  523. }
  524. }
  525. if (other)
  526. treatment |= GetMethodDefinitionTreatmentFromCustomAttributes(method);
  527. if (treatment != MethodDefinitionTreatment.None)
  528. ApplyProjection (method, new MethodDefinitionProjection (method, treatment));
  529. }
  530. static MethodDefinitionTreatment GetMethodDefinitionTreatmentFromCustomAttributes(MethodDefinition method)
  531. {
  532. var treatment = MethodDefinitionTreatment.None;
  533. foreach (var attribute in method.CustomAttributes)
  534. {
  535. var type = attribute.AttributeType;
  536. if (type.Namespace != "Windows.UI.Xaml")
  537. continue;
  538. if (type.Name == "TreatAsPublicMethodAttribute")
  539. treatment |= MethodDefinitionTreatment.Public;
  540. else if (type.Name == "TreatAsAbstractMethodAttribute")
  541. treatment |= MethodDefinitionTreatment.Abstract;
  542. }
  543. return treatment;
  544. }
  545. public static void ApplyProjection (MethodDefinition method, MethodDefinitionProjection projection)
  546. {
  547. if (projection == null)
  548. return;
  549. var treatment = projection.Treatment;
  550. if ((treatment & MethodDefinitionTreatment.Abstract) != 0)
  551. method.Attributes |= MethodAttributes.Abstract;
  552. if ((treatment & MethodDefinitionTreatment.Private) != 0)
  553. method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Private;
  554. if ((treatment & MethodDefinitionTreatment.Public) != 0)
  555. method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public;
  556. if ((treatment & MethodDefinitionTreatment.Runtime) != 0)
  557. method.ImplAttributes |= MethodImplAttributes.Runtime;
  558. if ((treatment & MethodDefinitionTreatment.InternalCall) != 0)
  559. method.ImplAttributes |= MethodImplAttributes.InternalCall;
  560. method.WindowsRuntimeProjection = projection;
  561. }
  562. public static MethodDefinitionProjection RemoveProjection (MethodDefinition method)
  563. {
  564. if (!method.IsWindowsRuntimeProjection)
  565. return null;
  566. var projection = method.WindowsRuntimeProjection;
  567. method.WindowsRuntimeProjection = null;
  568. method.Attributes = projection.Attributes;
  569. method.ImplAttributes = projection.ImplAttributes;
  570. method.Name = projection.Name;
  571. return projection;
  572. }
  573. public static void Project (FieldDefinition field)
  574. {
  575. var treatment = FieldDefinitionTreatment.None;
  576. var declaring_type = field.DeclaringType;
  577. if (declaring_type.Module.MetadataKind == MetadataKind.WindowsMetadata && field.IsRuntimeSpecialName && field.Name == "value__") {
  578. var base_type = declaring_type.BaseType;
  579. if (base_type != null && IsEnum (base_type))
  580. treatment = FieldDefinitionTreatment.Public;
  581. }
  582. if (treatment != FieldDefinitionTreatment.None)
  583. ApplyProjection (field, new FieldDefinitionProjection (field, treatment));
  584. }
  585. public static void ApplyProjection (FieldDefinition field, FieldDefinitionProjection projection)
  586. {
  587. if (projection == null)
  588. return;
  589. if (projection.Treatment == FieldDefinitionTreatment.Public)
  590. field.Attributes = (field.Attributes & ~FieldAttributes.FieldAccessMask) | FieldAttributes.Public;
  591. field.WindowsRuntimeProjection = projection;
  592. }
  593. public static FieldDefinitionProjection RemoveProjection (FieldDefinition field)
  594. {
  595. if (!field.IsWindowsRuntimeProjection)
  596. return null;
  597. var projection = field.WindowsRuntimeProjection;
  598. field.WindowsRuntimeProjection = null;
  599. field.Attributes = projection.Attributes;
  600. return projection;
  601. }
  602. static bool ImplementsRedirectedInterface (MemberReference member)
  603. {
  604. var declaring_type = member.DeclaringType;
  605. TypeReference type;
  606. switch (declaring_type.MetadataToken.TokenType) {
  607. case TokenType.TypeRef:
  608. type = declaring_type;
  609. break;
  610. case TokenType.TypeSpec:
  611. if (!declaring_type.IsGenericInstance)
  612. return false;
  613. type = ((TypeSpecification) declaring_type).ElementType;
  614. if (type.MetadataType != MetadataType.Class || type.MetadataToken.TokenType != TokenType.TypeRef)
  615. return false;
  616. break;
  617. default:
  618. return false;
  619. }
  620. var projection = RemoveProjection (type);
  621. var found = false;
  622. ProjectionInfo info;
  623. if (Projections.TryGetValue (type.Name, out info) && type.Namespace == info.WinRTNamespace) {
  624. found = true;
  625. }
  626. ApplyProjection (type, projection);
  627. return found;
  628. }
  629. public void AddVirtualReferences (Collection<AssemblyNameReference> references)
  630. {
  631. var corlib = GetCoreLibrary (references);
  632. corlib_version = corlib.Version;
  633. corlib.Version = version;
  634. if (virtual_references == null) {
  635. var winrt_references = GetAssemblyReferences (corlib);
  636. Interlocked.CompareExchange (ref virtual_references, winrt_references, null);
  637. }
  638. foreach (var reference in virtual_references)
  639. references.Add (reference);
  640. }
  641. public void RemoveVirtualReferences (Collection<AssemblyNameReference> references)
  642. {
  643. var corlib = GetCoreLibrary (references);
  644. corlib.Version = corlib_version;
  645. foreach (var reference in VirtualReferences)
  646. references.Remove (reference);
  647. }
  648. static AssemblyNameReference[] GetAssemblyReferences (AssemblyNameReference corlib)
  649. {
  650. var system_runtime = new AssemblyNameReference ("System.Runtime", version);
  651. var system_runtime_interopservices_windowsruntime = new AssemblyNameReference ("System.Runtime.InteropServices.WindowsRuntime", version);
  652. var system_objectmodel = new AssemblyNameReference ("System.ObjectModel", version);
  653. var system_runtime_windowsruntime = new AssemblyNameReference ("System.Runtime.WindowsRuntime", version);
  654. var system_runtime_windowsruntime_ui_xaml = new AssemblyNameReference ("System.Runtime.WindowsRuntime.UI.Xaml", version);
  655. var system_numerics_vectors = new AssemblyNameReference ("System.Numerics.Vectors", version);
  656. if (corlib.HasPublicKey) {
  657. system_runtime_windowsruntime.PublicKey =
  658. system_runtime_windowsruntime_ui_xaml.PublicKey = corlib.PublicKey;
  659. system_runtime.PublicKey =
  660. system_runtime_interopservices_windowsruntime.PublicKey =
  661. system_objectmodel.PublicKey =
  662. system_numerics_vectors.PublicKey = contract_pk;
  663. }
  664. else {
  665. system_runtime_windowsruntime.PublicKeyToken =
  666. system_runtime_windowsruntime_ui_xaml.PublicKeyToken = corlib.PublicKeyToken;
  667. system_runtime.PublicKeyToken =
  668. system_runtime_interopservices_windowsruntime.PublicKeyToken =
  669. system_objectmodel.PublicKeyToken =
  670. system_numerics_vectors.PublicKeyToken = contract_pk_token;
  671. }
  672. return new[] {
  673. system_runtime,
  674. system_runtime_interopservices_windowsruntime,
  675. system_objectmodel,
  676. system_runtime_windowsruntime,
  677. system_runtime_windowsruntime_ui_xaml,
  678. system_numerics_vectors,
  679. };
  680. }
  681. static AssemblyNameReference GetCoreLibrary (Collection<AssemblyNameReference> references)
  682. {
  683. foreach (var reference in references)
  684. if (reference.Name == "mscorlib")
  685. return reference;
  686. throw new BadImageFormatException ("Missing mscorlib reference in AssemblyRef table.");
  687. }
  688. AssemblyNameReference GetAssemblyReference (string name)
  689. {
  690. foreach (var assembly in VirtualReferences)
  691. if (assembly.Name == name)
  692. return assembly;
  693. throw new Exception ();
  694. }
  695. public static void Project (ICustomAttributeProvider owner, CustomAttribute attribute)
  696. {
  697. if (!IsWindowsAttributeUsageAttribute (owner, attribute))
  698. return;
  699. var treatment = CustomAttributeValueTreatment.None;
  700. var type = (TypeDefinition) owner;
  701. if (type.Namespace == "Windows.Foundation.Metadata") {
  702. if (type.Name == "VersionAttribute")
  703. treatment = CustomAttributeValueTreatment.VersionAttribute;
  704. else if (type.Name == "DeprecatedAttribute")
  705. treatment = CustomAttributeValueTreatment.DeprecatedAttribute;
  706. }
  707. if (treatment == CustomAttributeValueTreatment.None) {
  708. var multiple = HasAttribute (type, "Windows.Foundation.Metadata", "AllowMultipleAttribute");
  709. treatment = multiple ? CustomAttributeValueTreatment.AllowMultiple : CustomAttributeValueTreatment.AllowSingle;
  710. }
  711. if (treatment != CustomAttributeValueTreatment.None) {
  712. var attribute_targets = (AttributeTargets) attribute.ConstructorArguments [0].Value;
  713. ApplyProjection (attribute, new CustomAttributeValueProjection (attribute_targets, treatment));
  714. }
  715. }
  716. static bool IsWindowsAttributeUsageAttribute (ICustomAttributeProvider owner, CustomAttribute attribute)
  717. {
  718. if (owner.MetadataToken.TokenType != TokenType.TypeDef)
  719. return false;
  720. var constructor = attribute.Constructor;
  721. if (constructor.MetadataToken.TokenType != TokenType.MemberRef)
  722. return false;
  723. var declaring_type = constructor.DeclaringType;
  724. if (declaring_type.MetadataToken.TokenType != TokenType.TypeRef)
  725. return false;
  726. // declaring type is already projected
  727. return declaring_type.Name == "AttributeUsageAttribute" && declaring_type.Namespace == /*"Windows.Foundation.Metadata"*/"System";
  728. }
  729. static bool HasAttribute (TypeDefinition type, string @namespace, string name)
  730. {
  731. foreach (var attribute in type.CustomAttributes) {
  732. var attribute_type = attribute.AttributeType;
  733. if (attribute_type.Name == name && attribute_type.Namespace == @namespace)
  734. return true;
  735. }
  736. return false;
  737. }
  738. public static void ApplyProjection (CustomAttribute attribute, CustomAttributeValueProjection projection)
  739. {
  740. if (projection == null)
  741. return;
  742. bool version_or_deprecated;
  743. bool multiple;
  744. switch (projection.Treatment) {
  745. case CustomAttributeValueTreatment.AllowSingle:
  746. version_or_deprecated = false;
  747. multiple = false;
  748. break;
  749. case CustomAttributeValueTreatment.AllowMultiple:
  750. version_or_deprecated = false;
  751. multiple = true;
  752. break;
  753. case CustomAttributeValueTreatment.VersionAttribute:
  754. case CustomAttributeValueTreatment.DeprecatedAttribute:
  755. version_or_deprecated = true;
  756. multiple = true;
  757. break;
  758. default:
  759. throw new ArgumentException ();
  760. }
  761. var attribute_targets = (AttributeTargets) attribute.ConstructorArguments [0].Value;
  762. if (version_or_deprecated)
  763. attribute_targets |= AttributeTargets.Constructor | AttributeTargets.Property;
  764. attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, attribute_targets);
  765. attribute.Properties.Add (new CustomAttributeNamedArgument ("AllowMultiple", new CustomAttributeArgument (attribute.Module.TypeSystem.Boolean, multiple)));
  766. attribute.projection = projection;
  767. }
  768. public static CustomAttributeValueProjection RemoveProjection (CustomAttribute attribute)
  769. {
  770. if (attribute.projection == null)
  771. return null;
  772. var projection = attribute.projection;
  773. attribute.projection = null;
  774. attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, projection.Targets);
  775. attribute.Properties.Clear ();
  776. return projection;
  777. }
  778. }
  779. }