diff options
author | Jb Evain <jbevain@gmail.com> | 2015-07-07 19:53:04 +0300 |
---|---|---|
committer | Jb Evain <jbevain@gmail.com> | 2015-07-07 19:53:04 +0300 |
commit | 9ba8f0215f4826f827c3ef0ce261974ce9402500 (patch) | |
tree | d0fd671b45f0c5dbcb275ecc862d3f1f604fa427 | |
parent | 3654d4b9db4301dcaa07ca56c6acddd3799154e0 (diff) |
Add support for resolving calls to vararg methods
-rw-r--r-- | Mono.Cecil/MetadataResolver.cs | 21 | ||||
-rw-r--r-- | Test/Mono.Cecil.Tests/Linq.cs | 5 | ||||
-rw-r--r-- | 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<T> (this IEnumerable<T> self, Func<T, bool> 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 ()); }); } |