diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 589e5cd32..638176463 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -20,7 +20,7 @@ jobs:
- name: Test
run: dotnet test --no-build -c Debug Mono.Cecil.sln
linux:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
- name: Build
diff --git a/Directory.Build.props b/Directory.Build.props
index cadf4b9f2..e853ad2a1 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -22,7 +22,7 @@
true
-
+
diff --git a/Mono.Cecil.Tests.props b/Mono.Cecil.Tests.props
index 35cbbfc8b..e20ab0191 100644
--- a/Mono.Cecil.Tests.props
+++ b/Mono.Cecil.Tests.props
@@ -4,10 +4,10 @@
- 3.11.0
+ 3.14.0
- 3.12.0
+ 4.5.0
diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs
index 0756fa884..4564071e8 100644
--- a/Mono.Cecil/AssemblyReader.cs
+++ b/Mono.Cecil/AssemblyReader.cs
@@ -2508,7 +2508,7 @@ public Collection ReadCustomAttributes (ICustomAttributeProvide
if (module.IsWindowsMetadata ())
foreach (var custom_attribute in custom_attributes)
- WindowsRuntimeProjections.Project (owner, custom_attribute);
+ WindowsRuntimeProjections.Project (owner, custom_attributes, custom_attribute);
return custom_attributes;
}
diff --git a/Mono.Cecil/GenericParameter.cs b/Mono.Cecil/GenericParameter.cs
index 30dd73382..de746449b 100644
--- a/Mono.Cecil/GenericParameter.cs
+++ b/Mono.Cecil/GenericParameter.cs
@@ -165,6 +165,11 @@ public bool HasDefaultConstructorConstraint {
set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.DefaultConstructorConstraint, value); }
}
+ public bool AllowByRefLikeConstraint {
+ get { return attributes.GetAttributes ((ushort) GenericParameterAttributes.AllowByRefLikeConstraint); }
+ set { attributes = attributes.SetAttributes ((ushort) GenericParameterAttributes.AllowByRefLikeConstraint, value); }
+ }
+
#endregion
public GenericParameter (IGenericParameterProvider owner)
diff --git a/Mono.Cecil/GenericParameterAttributes.cs b/Mono.Cecil/GenericParameterAttributes.cs
index 149582cdb..51f094f47 100644
--- a/Mono.Cecil/GenericParameterAttributes.cs
+++ b/Mono.Cecil/GenericParameterAttributes.cs
@@ -22,6 +22,7 @@ public enum GenericParameterAttributes : ushort {
SpecialConstraintMask = 0x001c,
ReferenceTypeConstraint = 0x0004,
NotNullableValueTypeConstraint = 0x0008,
- DefaultConstructorConstraint = 0x0010
+ DefaultConstructorConstraint = 0x0010,
+ AllowByRefLikeConstraint = 0x0020,
}
}
diff --git a/Mono.Cecil/Import.cs b/Mono.Cecil/Import.cs
index 37cf932ae..6948359e9 100644
--- a/Mono.Cecil/Import.cs
+++ b/Mono.Cecil/Import.cs
@@ -159,6 +159,19 @@ enum ImportGenericKind {
{ typeof (object), ElementType.Object },
};
+ TypeReference ImportType (Type type, ImportGenericContext context, Type [] required_modifiers, Type [] optional_modifiers)
+ {
+ var import = ImportType (type, context);
+
+ foreach (var modifier in required_modifiers)
+ import = new RequiredModifierType (ImportType (modifier, context), import);
+
+ foreach (var modifier in optional_modifiers)
+ import = new OptionalModifierType (ImportType (modifier, context), import);
+
+ return import;
+ }
+
TypeReference ImportType (Type type, ImportGenericContext context)
{
return ImportType (type, context, ImportGenericKind.Open);
@@ -349,7 +362,7 @@ FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context)
return new FieldReference {
Name = field.Name,
DeclaringType = declaring_type,
- FieldType = ImportType (field.FieldType, context),
+ FieldType = ImportType (field.FieldType, context, field.GetRequiredCustomModifiers (), field.GetOptionalCustomModifiers ()),
};
} finally {
context.Pop ();
@@ -393,15 +406,17 @@ MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context
try {
var method_info = method as SR.MethodInfo;
reference.ReturnType = method_info != null
- ? ImportType (method_info.ReturnType, context)
+ ? ImportType (method_info.ReturnType, context, method_info.ReturnParameter.GetRequiredCustomModifiers (), method_info.ReturnParameter.GetOptionalCustomModifiers ())
: ImportType (typeof (void), default (ImportGenericContext));
var parameters = method.GetParameters ();
var reference_parameters = reference.Parameters;
- for (int i = 0; i < parameters.Length; i++)
+ for (int i = 0; i < parameters.Length; i++) {
+ var parameter = parameters [i];
reference_parameters.Add (
- new ParameterDefinition (ImportType (parameters [i].ParameterType, context)));
+ new ParameterDefinition (ImportType (parameter.ParameterType, context, parameter.GetRequiredCustomModifiers (), parameter.GetOptionalCustomModifiers ())));
+ }
reference.DeclaringType = declaring_type;
diff --git a/Mono.Cecil/MetadataResolver.cs b/Mono.Cecil/MetadataResolver.cs
index 6511b4187..29b786293 100644
--- a/Mono.Cecil/MetadataResolver.cs
+++ b/Mono.Cecil/MetadataResolver.cs
@@ -227,6 +227,22 @@ public virtual MethodDefinition Resolve (MethodReference method)
if (!type.HasMethods)
return null;
+
+ // This is here to handle privatescope. Aka CompilerControlled.
+ // GetMethod cannot correctly resolve a privatescope method when the method name is the same as another method in the type.
+ // because GetMethod operates on a MethodReference which doesn't have access to the MethodAttributes.
+ // privatescope methods are always private. There should also never be a MethodReference to a privatescope method.
+ // in other words, privatescope methods should always be referenced by their MethodDefinition.
+ //
+ // privatescope methods aside, if method is ever a MethodDefinition we don't need to go searching all of the methods on the type
+ // we can return the method directly. This avoids the cost of a linear search.
+ //
+ // So we have this optimization opportunity here.
+ // And we need to handle privatescope methods somehow, because GetMethod can't.
+ //
+ // and 2 birds one stone. This if check covers the optimization and privatescope handling.
+ if (method is MethodDefinition definition)
+ return definition;
return GetMethod (type, method);
}
@@ -264,6 +280,9 @@ public static MethodDefinition GetMethod (Collection methods,
if (!AreSame (method.ReturnType, reference.ReturnType))
continue;
+ if (method.HasThis != reference.HasThis)
+ continue;
+
if (method.IsVarArg () != reference.IsVarArg ())
continue;
@@ -331,6 +350,35 @@ static bool AreSame (TypeSpecification a, TypeSpecification b)
if (a.IsArray)
return AreSame ((ArrayType) a, (ArrayType) b);
+ if (a.IsFunctionPointer)
+ return AreSame ((FunctionPointerType) a, (FunctionPointerType) b);
+
+ return true;
+ }
+
+ static bool AreSame (FunctionPointerType a, FunctionPointerType b)
+ {
+ if (a.HasThis != b.HasThis)
+ return false;
+
+ if (a.CallingConvention != b.CallingConvention)
+ return false;
+
+ if (!AreSame (a.ReturnType, b.ReturnType))
+ return false;
+
+ if (a.ContainsGenericParameter != b.ContainsGenericParameter)
+ return false;
+
+ if (a.HasParameters != b.HasParameters)
+ return false;
+
+ if (!a.HasParameters)
+ return true;
+
+ if (!AreSame (a.Parameters, b.Parameters))
+ return false;
+
return true;
}
diff --git a/Mono.Cecil/WindowsRuntimeProjections.cs b/Mono.Cecil/WindowsRuntimeProjections.cs
index 6e83ba66e..b96a891b2 100644
--- a/Mono.Cecil/WindowsRuntimeProjections.cs
+++ b/Mono.Cecil/WindowsRuntimeProjections.cs
@@ -241,7 +241,7 @@ public static void Project (TypeDefinition type)
treatment = TypeDefinitionTreatment.PrefixWindowsRuntimeName;
if (treatment == TypeDefinitionTreatment.PrefixWindowsRuntimeName || treatment == TypeDefinitionTreatment.NormalType)
- if (!type.IsInterface && HasAttribute (type, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute"))
+ if (!type.IsInterface && HasAttribute (type.CustomAttributes, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute"))
treatment |= TypeDefinitionTreatment.Abstract;
}
else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && IsClrImplementationType (type))
@@ -860,7 +860,7 @@ AssemblyNameReference GetAssemblyReference (string name)
throw new Exception ();
}
- public static void Project (ICustomAttributeProvider owner, CustomAttribute attribute)
+ public static void Project (ICustomAttributeProvider owner, Collection owner_attributes, CustomAttribute attribute)
{
if (!IsWindowsAttributeUsageAttribute (owner, attribute))
return;
@@ -876,7 +876,7 @@ public static void Project (ICustomAttributeProvider owner, CustomAttribute attr
}
if (treatment == CustomAttributeValueTreatment.None) {
- var multiple = HasAttribute (type, "Windows.Foundation.Metadata", "AllowMultipleAttribute");
+ var multiple = HasAttribute (owner_attributes, "Windows.Foundation.Metadata", "AllowMultipleAttribute");
treatment = multiple ? CustomAttributeValueTreatment.AllowMultiple : CustomAttributeValueTreatment.AllowSingle;
}
@@ -905,9 +905,9 @@ static bool IsWindowsAttributeUsageAttribute (ICustomAttributeProvider owner, Cu
return declaring_type.Name == "AttributeUsageAttribute" && declaring_type.Namespace == /*"Windows.Foundation.Metadata"*/"System";
}
- static bool HasAttribute (TypeDefinition type, string @namespace, string name)
+ static bool HasAttribute (Collection attributes, string @namespace, string name)
{
- foreach (var attribute in type.CustomAttributes) {
+ foreach (var attribute in attributes) {
var attribute_type = attribute.AttributeType;
if (attribute_type.Name == name && attribute_type.Namespace == @namespace)
return true;
diff --git a/Mono.Security.Cryptography/CryptoService.cs b/Mono.Security.Cryptography/CryptoService.cs
index 3877debfa..1da81b1e1 100644
--- a/Mono.Security.Cryptography/CryptoService.cs
+++ b/Mono.Security.Cryptography/CryptoService.cs
@@ -26,6 +26,8 @@ namespace Mono.Cecil {
static class CryptoService {
+ static SHA1 CreateSHA1 () => new SHA1CryptoServiceProvider ();
+
public static byte [] GetPublicKey (WriterParameters parameters)
{
using (var rsa = parameters.CreateRSA ()) {
@@ -93,7 +95,7 @@ static byte [] HashStream (Stream stream, ImageWriter writer, out int strong_nam
+ (strong_name_directory.VirtualAddress - text.VirtualAddress));
var strong_name_length = (int) strong_name_directory.Size;
- var sha1 = new SHA1Managed ();
+ var sha1 = CreateSHA1 ();
var buffer = new byte [buffer_size];
using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) {
stream.Seek (0, SeekOrigin.Begin);
@@ -131,7 +133,7 @@ public static byte [] ComputeHash (Stream stream)
{
const int buffer_size = 8192;
- var sha1 = new SHA1Managed ();
+ var sha1 = CreateSHA1 ();
var buffer = new byte [buffer_size];
using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write))
@@ -142,7 +144,7 @@ public static byte [] ComputeHash (Stream stream)
public static byte [] ComputeHash (params ByteBuffer [] buffers)
{
- var sha1 = new SHA1Managed ();
+ var sha1 = CreateSHA1 ();
using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) {
for (int i = 0; i < buffers.Length; i++) {
diff --git a/ProjectInfo.cs b/ProjectInfo.cs
index fe891346c..c7ffe5f04 100644
--- a/ProjectInfo.cs
+++ b/ProjectInfo.cs
@@ -15,6 +15,6 @@
[assembly: ComVisible (false)]
-[assembly: AssemblyVersion ("0.11.4.0")]
-[assembly: AssemblyFileVersion ("0.11.4.0")]
-[assembly: AssemblyInformationalVersion ("0.11.4.0")]
+[assembly: AssemblyVersion ("0.11.5.0")]
+[assembly: AssemblyFileVersion ("0.11.5.0")]
+[assembly: AssemblyInformationalVersion ("0.11.5.0")]
diff --git a/Test/Mono.Cecil.Tests/ImageReadTests.cs b/Test/Mono.Cecil.Tests/ImageReadTests.cs
index f663b60ca..fb5c558c6 100644
--- a/Test/Mono.Cecil.Tests/ImageReadTests.cs
+++ b/Test/Mono.Cecil.Tests/ImageReadTests.cs
@@ -182,7 +182,7 @@ public void MetroAssembly ()
[Test]
public void WindowsRuntimeComponentAssembly ()
{
- var resolver = WindowsRuntimeAssemblyResolver.CreateInstance ();
+ var resolver = WindowsRuntimeAssemblyResolver.CreateInstance (applyWindowsRuntimeProjections: false);
if (resolver == null)
return;
diff --git a/Test/Mono.Cecil.Tests/MethodTests.cs b/Test/Mono.Cecil.Tests/MethodTests.cs
index b878613c0..821fb139e 100644
--- a/Test/Mono.Cecil.Tests/MethodTests.cs
+++ b/Test/Mono.Cecil.Tests/MethodTests.cs
@@ -2,8 +2,9 @@
using System.Linq;
using Mono.Cecil;
+using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
-
+using Mono.Collections.Generic;
using NUnit.Framework;
namespace Mono.Cecil.Tests {
@@ -221,5 +222,153 @@ public void ReturnParameterMethod ()
Assert.IsNotNull (method);
Assert.AreEqual (method, method.MethodReturnType.Parameter.Method);
}
+
+ [Test]
+ public void InstanceAndStaticMethodComparison ()
+ {
+ TestIL ("others.il", module => {
+ var others = module.GetType ("Others");
+ var instance_method = others.Methods.Single (m => m.Name == "SameMethodNameInstanceStatic" && m.HasThis);
+ var static_method_reference = new MethodReference ("SameMethodNameInstanceStatic", instance_method.ReturnType, others)
+ {
+ HasThis = false
+ };
+
+ Assert.AreNotEqual(instance_method, static_method_reference.Resolve ());
+ });
+ }
+
+ [Test]
+ public void FunctionPointerArgumentOverload ()
+ {
+ TestIL ("others.il", module => {
+ var others = module.GetType ("Others");
+ var overloaded_methods = others.Methods.Where (m => m.Name == "OverloadedWithFpArg").ToArray ();
+ // Manually create the function-pointer type so `AreSame` won't exit early due to reference equality
+ var overloaded_method_int_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
+ {
+ HasThis = false,
+ Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
+ HasThis = false,
+ ReturnType = module.TypeSystem.Int32,
+ Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
+ }) }
+ };
+
+ var overloaded_method_long_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
+ {
+ HasThis = false,
+ Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
+ HasThis = false,
+ ReturnType = module.TypeSystem.Int32,
+ Parameters = { new ParameterDefinition (module.TypeSystem.Int64) }
+ }) }
+ };
+
+ var overloaded_method_cdecl_reference = new MethodReference ("OverloadedWithFpArg", module.TypeSystem.Void, others)
+ {
+ HasThis = false,
+ Parameters = { new ParameterDefinition ("X", ParameterAttributes.None, new FunctionPointerType () {
+ CallingConvention = MethodCallingConvention.C,
+ HasThis = false,
+ ReturnType = module.TypeSystem.Int32,
+ Parameters = { new ParameterDefinition (module.TypeSystem.Int32) }
+ }) }
+ };
+
+
+ Assert.AreEqual (overloaded_methods[0], overloaded_method_int_reference.Resolve ());
+ Assert.AreEqual (overloaded_methods[1], overloaded_method_long_reference.Resolve ());
+ Assert.AreEqual (overloaded_methods[2], overloaded_method_cdecl_reference.Resolve ());
+ });
+ }
+
+ [Test]
+ public void PrivateScope ()
+ {
+ TestIL ("privatescope.il", module => {
+ var foo = module.GetType ("Foo");
+ var call_same_name_methods = foo.GetMethod ("CallSameNameMethods");
+ var call_instructions = call_same_name_methods.Body.Instructions
+ .Where (ins => ins.OpCode.Code == Code.Call)
+ .ToArray ();
+
+ var first_same_name_index = 2;
+
+ // The first method will be the normal non-privatescope method.
+ var first_call_resolved = ((MethodReference)call_instructions [0].Operand).Resolve ();
+ var expected_first_call_resolved = foo.Methods [first_same_name_index];
+ Assert.IsFalse(first_call_resolved.IsCompilerControlled);
+ Assert.AreEqual(expected_first_call_resolved, first_call_resolved);
+
+ // This is the first privatescope method.
+ var second_call_resolved = ((MethodReference)call_instructions [1].Operand).Resolve();
+ var expected_second_call_resolved = foo.Methods [first_same_name_index + 1];
+
+ // Sanity check to make sure the ordering assumptions were correct.
+ Assert.IsTrue(expected_second_call_resolved.IsCompilerControlled, "The expected method should have been compiler controlled.");
+
+ // The equality failure isn't going to be very helpful since both methods will have the same ToString value,
+ // so before we assert equality, we'll assert that the method is compiler controlled because that is the key difference
+ Assert.IsTrue(second_call_resolved.IsCompilerControlled, "Expected the method reference to resolve to a compiler controlled method");
+ Assert.AreEqual(expected_second_call_resolved, second_call_resolved);
+
+ // This is the second privatescope method.
+ var third_call_resolved = ((MethodReference)call_instructions [2].Operand).Resolve ();
+ var expected_third_call_resolved = foo.Methods [first_same_name_index + 2];
+
+ // Sanity check to make sure the ordering assumptions were correct.
+ Assert.IsTrue(expected_third_call_resolved.IsCompilerControlled, "The expected method should have been compiler controlled.");
+
+ // The equality failure isn't going to be very helpful since both methods will have the same ToString value,
+ // so before we assert equality, we'll assert that the method is compiler controlled because that is the key difference
+ Assert.IsTrue(third_call_resolved.IsCompilerControlled, "Expected the method reference to resolve to a compiler controlled method");
+ Assert.AreEqual(expected_third_call_resolved, third_call_resolved);
+ });
+ }
+
+ [Test]
+ public void PrivateScopeGeneric ()
+ {
+ TestIL ("privatescope.il", module => {
+ var foo = module.GetType ("Foo");
+ var call_same_name_methods = foo.GetMethod ("CallSameNameMethodsGeneric");
+ var call_instructions = call_same_name_methods.Body.Instructions
+ .Where (ins => ins.OpCode.Code == Code.Call)
+ .ToArray ();
+
+ var first_same_name_generic_index = 6;
+
+ // The first method will be the normal non-privatescope method.
+ var first_call_resolved = ((MethodReference)call_instructions [0].Operand).Resolve();
+ var expected_first_call_resolved = foo.Methods [first_same_name_generic_index];
+ Assert.IsFalse(first_call_resolved.IsCompilerControlled);
+ Assert.AreEqual(expected_first_call_resolved, first_call_resolved);
+
+ // This is the first privatescope method.
+ var second_call_resolved = ((MethodReference)call_instructions [1].Operand).Resolve();
+ var expected_second_call_resolved = foo.Methods [first_same_name_generic_index + 1];
+
+ // Sanity check to make sure the ordering assumptions were correct.
+ Assert.IsTrue(expected_second_call_resolved.IsCompilerControlled, "The expected method should have been compiler controlled.");
+
+ // The equality failure isn't going to be very helpful since both methods will have the same ToString value,
+ // so before we assert equality, we'll assert that the method is compiler controlled because that is the key difference
+ Assert.IsTrue (second_call_resolved.IsCompilerControlled, "Expected the method reference to resolve to a compiler controlled method");
+ Assert.AreEqual(expected_second_call_resolved, second_call_resolved);
+
+ // This is the second privatescope method.
+ var third_call_resolved = ((MethodReference)call_instructions [2].Operand).Resolve();
+ var expected_third_call_resolved = foo.Methods [first_same_name_generic_index + 2];
+
+ // Sanity check to make sure the ordering assumptions were correct.
+ Assert.IsTrue(expected_third_call_resolved.IsCompilerControlled, "The expected method should have been compiler controlled.");
+
+ // The equality failure isn't going to be very helpful since both methods will have the same ToString value,
+ // so before we assert equality, we'll assert that the method is compiler controlled because that is the key difference
+ Assert.IsTrue(third_call_resolved.IsCompilerControlled, "Expected the method reference to resolve to a compiler controlled method");
+ Assert.AreEqual(expected_third_call_resolved, third_call_resolved);
+ });
+ }
}
}
diff --git a/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs b/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs
index 65616294f..4f6aaf6ec 100644
--- a/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs
+++ b/Test/Mono.Cecil.Tests/WindowsRuntimeAssemblyResolver.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using Microsoft.Win32;
namespace Mono.Cecil.Tests {
@@ -10,12 +11,12 @@ public class WindowsRuntimeAssemblyResolver : DefaultAssemblyResolver {
readonly Dictionary assemblies = new Dictionary ();
- public static WindowsRuntimeAssemblyResolver CreateInstance ()
+ public static WindowsRuntimeAssemblyResolver CreateInstance (bool applyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return null;
try {
- return new WindowsRuntimeAssemblyResolver ();
+ return new WindowsRuntimeAssemblyResolver (applyWindowsRuntimeProjections);
} catch {
return null;
}
@@ -30,20 +31,30 @@ public override AssemblyDefinition Resolve (AssemblyNameReference name)
return base.Resolve (name);
}
- private WindowsRuntimeAssemblyResolver ()
+ private WindowsRuntimeAssemblyResolver (bool applyWindowsRuntimeProjections)
{
- LoadWindowsSdk ("v8.1", "8.1", (installationFolder) => {
- var fileName = Path.Combine (installationFolder, @"References\CommonConfiguration\Neutral\Annotated\Windows.winmd");
- var assembly = AssemblyDefinition.ReadAssembly (fileName);
- Register (assembly);
- });
+ var readerParameters = new ReaderParameters {
+ ApplyWindowsRuntimeProjections = applyWindowsRuntimeProjections
+ };
LoadWindowsSdk ("v10.0", "10", (installationFolder) => {
var referencesFolder = Path.Combine (installationFolder, "References");
var assemblies = Directory.GetFiles (referencesFolder, "*.winmd", SearchOption.AllDirectories);
+
+ var latestVersionDir = Directory.GetDirectories (Path.Combine (installationFolder, "UnionMetadata"))
+ .Where (d => Path.GetFileName (d) != "Facade")
+ .OrderBy (d => Path.GetFileName (d))
+ .Last ();
+
+ var windowsWinMdPath = Path.Combine (latestVersionDir, "Windows.winmd");
+ if (!File.Exists (windowsWinMdPath))
+ throw new FileNotFoundException (windowsWinMdPath);
+
+ var windowsWinmdAssembly = AssemblyDefinition.ReadAssembly (windowsWinMdPath, readerParameters);
+ Register (windowsWinmdAssembly);
foreach (var assemblyPath in assemblies) {
- var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
+ var assembly = AssemblyDefinition.ReadAssembly (assemblyPath, readerParameters);
Register (assembly);
}
});
diff --git a/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs b/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
index 538727329..ae443930b 100644
--- a/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
+++ b/Test/Mono.Cecil.Tests/WindowsRuntimeProjectionsTests.cs
@@ -17,19 +17,21 @@ public abstract class BaseWindowsRuntimeProjectionsTests : BaseTestFixture {
protected abstract string [] ManagedClassTypeNames { get; }
protected abstract string [] CustomListTypeNames { get; }
- [Test]
- public void CanReadMetadataType ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanReadMetadataType (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
TestModule (ModuleName, (module) => {
Assert.AreEqual (ExpectedMetadataKind, module.MetadataKind);
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void CanProjectParametersAndReturnTypes ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectParametersAndReturnTypes (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -48,11 +50,12 @@ public void CanProjectParametersAndReturnTypes ()
Assert.AreEqual (listSetter.Parameters.Count, 1);
Assert.AreEqual (listSetter.Parameters [0].ParameterType.FullName, "System.Collections.Generic.IList`1");
}
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void CanProjectInterfaces ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectInterfaces (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -64,16 +67,41 @@ public void CanProjectInterfaces ()
Assert.IsNotNull (type.Interfaces.SingleOrDefault (i => i.InterfaceType.FullName == "System.Collections.Generic.IList`1"));
Assert.IsNotNull (type.Interfaces.SingleOrDefault (i => i.InterfaceType.FullName == "System.Collections.Generic.IEnumerable`1"));
}
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
+ }
+
+ ///
+ /// This test exists to verify a StackOverflowException that started happening with https://github.com/jbevain/cecil/pull/843
+ /// and was fixed by https://github.com/jbevain/cecil/pull/879
+ ///
+ /// The windows runtime sdk assemblies must be read with ApplyWindowsRuntimeProjections in order for the StackOverflowException to happen
+ ///
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanAvoidCircleAttributeReading (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
+ {
+ if (Platform.OnMono)
+ return;
+
+ TestModule (ModuleName, (module) => {
+
+ var windowsWinMd = module.AssemblyResolver.Resolve (new AssemblyNameReference ("Windows", null));
+
+ var problematicType = windowsWinMd.MainModule.GetType ("Windows.Foundation.Metadata.ActivatableAttribute");
+
+ Assert.Greater (problematicType.CustomAttributes.Count, 0, "Expected one or more attributes");
+
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void CanStripType ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanStripType (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
- var assemblyResolver = WindowsRuntimeAssemblyResolver.CreateInstance ();
+ var assemblyResolver = WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections);
TestModule (ModuleName, (originalModule) => {
var types = CustomListTypeNames.Select (typeName => originalModule.Types.Single (t => t.Name == typeName)).ToArray ();
@@ -107,8 +135,9 @@ public class ManagedWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjectio
protected override string [] CustomListTypeNames { get { return new [] { "CustomList", "CustomList" }; } }
- [Test]
- public void CanProjectClasses ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectClasses (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -129,11 +158,12 @@ public void CanProjectClasses ()
var winrtSomeOtherClassType = module.Types.Single (t => t.Name == "SomeOtherClass");
Assert.AreEqual ("SomeOtherClass", winrtSomeOtherClassType.WindowsRuntimeProjection.Name);
Assert.AreEqual (TypeDefinitionTreatment.PrefixWindowsRuntimeName, winrtSomeOtherClassType.WindowsRuntimeProjection.Treatment);
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void VerifyTypeReferenceToProjectedTypeInAttributeArgumentReferencesUnmangledTypeName()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void VerifyTypeReferenceToProjectedTypeInAttributeArgumentReferencesUnmangledTypeName(bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -147,7 +177,7 @@ public void VerifyTypeReferenceToProjectedTypeInAttributeArgumentReferencesUnman
var attributeArgument = (TypeReference)attribute.ConstructorArguments[0].Value;
Assert.AreEqual("ManagedWinmd.ClassWithAsyncMethod/d__0", attributeArgument.FullName);
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance(), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance(readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
}
@@ -162,8 +192,9 @@ public class NativeWindowsRuntimeProjectionsTests : BaseWindowsRuntimeProjection
protected override string [] CustomListTypeNames { get { return new [] { "CustomList" }; } }
- [Test]
- public void CanProjectAndRedirectInterfaces ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectAndRedirectInterfaces (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -213,11 +244,12 @@ public void CanProjectAndRedirectInterfaces ()
Assert.AreEqual (0, customPropertySetClass.Interfaces[6].CustomAttributes.Count);
Assert.AreEqual ("Windows.Foundation.Collections.IIterable`1>", customPropertySetClass.Interfaces[6].InterfaceType.FullName);
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void CanProjectInterfaceMethods ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectInterfaceMethods (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -256,11 +288,12 @@ public void CanProjectInterfaceMethods ()
Assert.AreEqual (customListClass.Methods[25].FullName, "System.Boolean NativeWinmd.CustomList::Remove(System.Int32)");
Assert.AreEqual (customListClass.Methods[26].FullName, "System.Collections.Generic.IEnumerator`1 NativeWinmd.CustomList::GetEnumerator()");
Assert.AreEqual (customListClass.Methods[27].FullName, "System.Collections.IEnumerator NativeWinmd.CustomList::GetEnumerator()");
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
- [Test]
- public void CanProjectMethodOverrides ()
+ [TestCase (true)]
+ [TestCase (false)]
+ public void CanProjectMethodOverrides (bool readSdkAssembliesWithApplyWindowsRuntimeProjections)
{
if (Platform.OnMono)
return;
@@ -299,7 +332,7 @@ public void CanProjectMethodOverrides ()
Assert.AreEqual (customListClass.Methods[26].Overrides[0].FullName, "System.Collections.Generic.IEnumerator`1 System.Collections.Generic.IEnumerable`1::GetEnumerator()");
Assert.AreEqual (customListClass.Methods[27].Overrides[0].FullName, "System.Collections.IEnumerator System.Collections.IEnumerable::GetEnumerator()");
- }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (), applyWindowsRuntimeProjections: true);
+ }, verify: false, assemblyResolver: WindowsRuntimeAssemblyResolver.CreateInstance (readSdkAssembliesWithApplyWindowsRuntimeProjections), applyWindowsRuntimeProjections: true);
}
}
}
diff --git a/Test/Resources/il/others.il b/Test/Resources/il/others.il
index 60713af30..7be104208 100644
--- a/Test/Resources/il/others.il
+++ b/Test/Resources/il/others.il
@@ -78,4 +78,29 @@
.other instance void Others::dang_Handler (class [mscorlib]System.EventHandler)
.other instance void Others::fang_Handler (class [mscorlib]System.EventHandler)
}
+
+ .method public static void OverloadedWithFpArg(method int32 *(int32) X) cil managed
+ {
+ ret
+ }
+
+ .method public static void OverloadedWithFpArg(method int32 *(int64) X) cil managed
+ {
+ ret
+ }
+
+ .method public static void OverloadedWithFpArg(method unmanaged cdecl int32 *(int32) X) cil managed
+ {
+ ret
+ }
+
+ .method public instance void SameMethodNameInstanceStatic() cil managed
+ {
+ ret
+ }
+
+ .method public static void SameMethodNameInstanceStatic() cil managed
+ {
+ ret
+ } // end of static method MethodNameTests::MethodName
}
diff --git a/Test/Resources/il/privatescope.il b/Test/Resources/il/privatescope.il
new file mode 100644
index 000000000..12aadee1e
--- /dev/null
+++ b/Test/Resources/il/privatescope.il
@@ -0,0 +1,77 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
+ .ver 2:0:0:0
+}
+
+.assembly PrivateScope {}
+
+.module PrivateScope.dll
+
+.class private auto ansi Foo {
+
+ .method public specialname rtspecialname instance void .ctor () cil managed
+ {
+ ldarg.0
+ call instance void [mscorlib]System.Object::.ctor ()
+ ret
+ }
+
+ .method public instance void CallSameNameMethods() cil managed
+ {
+ ldarg.0
+ call instance void Foo::'SameName'()
+ ldarg.0
+ call instance void Foo::'SameName$PST0600A3BA'()
+ ldarg.0
+ call instance void Foo::'SameName$PST0600A3BC'()
+ ret
+ }
+
+ .method public hidebysig
+ instance void 'SameName' () cil managed
+ {
+ ret
+ }
+
+ .method privatescope
+ instance void 'SameName$PST0600A3BA' () cil managed
+ {
+ ret
+ }
+
+ .method privatescope
+ instance void 'SameName$PST0600A3BC' () cil managed
+ {
+ ret
+ }
+
+ .method public instance void CallSameNameMethodsGeneric() cil managed
+ {
+ ldarg.0
+ call instance void Foo::'SameNameGeneric'()
+ ldarg.0
+ call instance void Foo::'SameNameGeneric$PST0600A3BD'()
+ ldarg.0
+ call instance void Foo::'SameNameGeneric$PST0600A3BE'()
+ ret
+ }
+
+ .method public hidebysig
+ instance void 'SameNameGeneric' () cil managed
+ {
+ ret
+ }
+
+ .method privatescope
+ instance void 'SameNameGeneric$PST0600A3BD' () cil managed
+ {
+ ret
+ }
+
+ .method privatescope
+ instance void 'SameNameGeneric$PST0600A3BE' () cil managed
+ {
+ ret
+ }
+}
\ No newline at end of file