From 9ba8f0215f4826f827c3ef0ce261974ce9402500 Mon Sep 17 00:00:00 2001 From: Jb Evain Date: Tue, 7 Jul 2015 18:53:04 +0200 Subject: Add support for resolving calls to vararg methods --- Mono.Cecil/MetadataResolver.cs | 21 +++++++++++++++++++++ Test/Mono.Cecil.Tests/Linq.cs | 5 +++++ Test/Mono.Cecil.Tests/MethodTests.cs | 18 +++++++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Mono.Cecil/MetadataResolver.cs b/Mono.Cecil/MetadataResolver.cs index 97d3c00..70d9265 100644 --- a/Mono.Cecil/MetadataResolver.cs +++ b/Mono.Cecil/MetadataResolver.cs @@ -258,6 +258,12 @@ namespace Mono.Cecil { if (!AreSame (method.ReturnType, reference.ReturnType)) continue; + if (method.IsVarArg () != reference.IsVarArg ()) + continue; + + if (method.IsVarArg () && IsVarArgCallTo (method, reference)) + return method; + if (method.HasParameters != reference.HasParameters) continue; @@ -290,6 +296,21 @@ namespace Mono.Cecil { return true; } + private static bool IsVarArgCallTo (MethodDefinition method, MethodReference reference) + { + if (method.Parameters.Count >= reference.Parameters.Count) + return false; + + if (reference.GetSentinelPosition () != method.Parameters.Count) + return false; + + for (int i = 0; i < method.Parameters.Count; i++) + if (!AreSame (method.Parameters [i].ParameterType, reference.Parameters [i].ParameterType)) + return false; + + return true; + } + static bool AreSame (TypeSpecification a, TypeSpecification b) { if (!AreSame (a.ElementType, b.ElementType)) diff --git a/Test/Mono.Cecil.Tests/Linq.cs b/Test/Mono.Cecil.Tests/Linq.cs index 4f870e0..d1fac18 100644 --- a/Test/Mono.Cecil.Tests/Linq.cs +++ b/Test/Mono.Cecil.Tests/Linq.cs @@ -41,6 +41,11 @@ namespace System.Linq { return enumerator.Current; } } + + public static T First (this IEnumerable self, Func predicate) + { + return self.Where (t => predicate (t)).First (); + } } } diff --git a/Test/Mono.Cecil.Tests/MethodTests.cs b/Test/Mono.Cecil.Tests/MethodTests.cs index bc76aa6..bbf1742 100644 --- a/Test/Mono.Cecil.Tests/MethodTests.cs +++ b/Test/Mono.Cecil.Tests/MethodTests.cs @@ -155,18 +155,22 @@ namespace Mono.Cecil.Tests { Assert.IsTrue (bar.IsVarArg ()); Assert.IsFalse (baz.IsVarArg ()); - Assert.IsTrue(foo.IsVarArg ()); + Assert.IsTrue (foo.IsVarArg ()); - var bar_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x000a).First ().Operand; + var foo_reference = (MethodReference) baz.Body.Instructions.First (i => i.Offset == 0x000a).Operand; - Assert.IsTrue (bar_reference.IsVarArg ()); - Assert.AreEqual (0, bar_reference.GetSentinelPosition ()); + Assert.IsTrue (foo_reference.IsVarArg ()); + Assert.AreEqual (0, foo_reference.GetSentinelPosition ()); - var foo_reference = (MethodReference) baz.Body.Instructions.Where (i => i.Offset == 0x0023).First ().Operand; + Assert.AreEqual (foo, foo_reference.Resolve ()); - Assert.IsTrue (foo_reference.IsVarArg ()); + var bar_reference = (MethodReference) baz.Body.Instructions.First (i => i.Offset == 0x0023).Operand; + + Assert.IsTrue (bar_reference.IsVarArg ()); + + Assert.AreEqual (1, bar_reference.GetSentinelPosition ()); - Assert.AreEqual (1, foo_reference.GetSentinelPosition ()); + Assert.AreEqual (bar, bar_reference.Resolve ()); }); } -- cgit v1.2.3